~ubuntu-branches/ubuntu/karmic/openipmi/karmic

« back to all changes in this revision

Viewing changes to lib/opq.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2005-07-04 21:29:17 UTC
  • Revision ID: james.westby@ubuntu.com-20050704212917-igddk5jawjmhrlay
Tags: upstream-2.0.1
Import upstream version 2.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * opq.c
 
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,2003 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
#include <stdlib.h>
 
35
#include <string.h>
 
36
 
 
37
#include <OpenIPMI/os_handler.h>
 
38
 
 
39
#include <OpenIPMI/internal/ipmi_int.h>
 
40
#include <OpenIPMI/internal/ilist.h>
 
41
#include <OpenIPMI/internal/opq.h>
 
42
 
 
43
typedef struct opq_elem_s
 
44
{
 
45
    int               block;
 
46
    opq_handler_cb    handler;
 
47
    void              *handler_data;
 
48
    opq_done_cb       done;
 
49
    void              *done_data;
 
50
    struct opq_elem_s *next;
 
51
} opq_elem_t;
 
52
 
 
53
struct opq_s
 
54
{
 
55
    ilist_t        *ops;
 
56
    os_hnd_lock_t  *lock;
 
57
    int            in_handler;
 
58
    os_handler_t   *os_hnd;
 
59
    opq_done_cb    done_handler;
 
60
    void           *done_data;
 
61
    int            blocked;
 
62
};
 
63
 
 
64
static void
 
65
opq_lock(opq_t *opq)
 
66
{
 
67
    if (opq->lock)
 
68
        opq->os_hnd->lock(opq->os_hnd, opq->lock);
 
69
}
 
70
 
 
71
static void
 
72
opq_unlock(opq_t *opq)
 
73
{
 
74
    if (opq->lock)
 
75
        opq->os_hnd->unlock(opq->os_hnd, opq->lock);
 
76
}
 
77
 
 
78
opq_t *
 
79
opq_alloc(os_handler_t *os_hnd)
 
80
{
 
81
    int   rv;
 
82
    opq_t *opq;
 
83
 
 
84
    opq = ipmi_mem_alloc(sizeof(*opq));
 
85
    if (!opq)
 
86
        return NULL;
 
87
    memset(opq, 0, sizeof(*opq));
 
88
 
 
89
    opq->os_hnd = os_hnd;
 
90
    opq->in_handler = 0;
 
91
    opq->ops = alloc_ilist();
 
92
    if (!(opq->ops)) {
 
93
        ipmi_mem_free(opq);
 
94
        return NULL;
 
95
    }
 
96
 
 
97
    if (os_hnd->create_lock) {
 
98
        rv = os_hnd->create_lock(opq->os_hnd, &(opq->lock));
 
99
        if (rv) {
 
100
            free_ilist(opq->ops);
 
101
            ipmi_mem_free(opq);
 
102
            return NULL;
 
103
        }
 
104
    } else {
 
105
        opq->lock = NULL;
 
106
    }
 
107
 
 
108
    return opq;
 
109
}
 
110
 
 
111
static void
 
112
opq_destroy_item(ilist_iter_t *iter, void *item, void *cb_data)
 
113
{
 
114
    opq_elem_t *elem = (opq_elem_t *) item;
 
115
 
 
116
    elem->handler(elem->handler_data, 1);
 
117
    ipmi_mem_free(elem);
 
118
}
 
119
 
 
120
void
 
121
opq_destroy(opq_t *opq)
 
122
{
 
123
    ilist_iter(opq->ops, opq_destroy_item, NULL);
 
124
    free_ilist(opq->ops);
 
125
    if (opq->lock)
 
126
        opq->os_hnd->destroy_lock(opq->os_hnd, opq->lock);
 
127
    ipmi_mem_free(opq);
 
128
}
 
129
 
 
130
int
 
131
opq_new_op(opq_t *opq, opq_handler_cb handler, void *cb_data, int nowait)
 
132
{
 
133
    opq_elem_t *elem;
 
134
 
 
135
    opq_lock(opq);
 
136
    if (opq->in_handler) {
 
137
        if (nowait) {
 
138
            opq_unlock(opq);
 
139
            return -1;
 
140
        }
 
141
        elem = ipmi_mem_alloc(sizeof(*elem));
 
142
        if (!elem)
 
143
            goto out_err;
 
144
        elem->handler = handler;
 
145
        elem->done = NULL;
 
146
        elem->handler_data = cb_data;
 
147
        elem->block = 1;
 
148
        if (! ilist_add_tail(opq->ops, elem, NULL)) {
 
149
            ipmi_mem_free(elem);
 
150
            goto out_err;
 
151
        }
 
152
        opq->blocked = 0;
 
153
        opq_unlock(opq);
 
154
    } else {
 
155
        opq->blocked = 0;
 
156
        opq->in_handler = 1;
 
157
        opq->done_handler = NULL;
 
158
        opq_unlock(opq);
 
159
        handler(cb_data, 0);
 
160
    }
 
161
 
 
162
    return 1;
 
163
 
 
164
 out_err:
 
165
    opq_unlock(opq);
 
166
    return 0;
 
167
}
 
168
 
 
169
int
 
170
opq_new_op_with_done(opq_t          *opq,
 
171
                     opq_handler_cb handler,
 
172
                     void           *handler_data,
 
173
                     opq_done_cb    done,
 
174
                     void           *done_data)
 
175
{
 
176
    opq_elem_t *elem;
 
177
 
 
178
    opq_lock(opq);
 
179
    if (opq->in_handler) {
 
180
        elem = ipmi_mem_alloc(sizeof(*elem));
 
181
        if (!elem)
 
182
            goto out_err;
 
183
        elem->handler = handler;
 
184
        elem->handler_data = handler_data;
 
185
        elem->done = done;
 
186
        elem->done_data = done_data;
 
187
        elem->block = opq->blocked;
 
188
        if (! ilist_add_tail(opq->ops, elem, NULL)) {
 
189
            ipmi_mem_free(elem);
 
190
            goto out_err;
 
191
        }
 
192
        opq->blocked = 0;
 
193
        opq_unlock(opq);
 
194
    } else {
 
195
        opq->blocked = 0;
 
196
        opq->in_handler = 1;
 
197
        opq->done_handler = done;
 
198
        opq->done_data = done_data;
 
199
        opq_unlock(opq);
 
200
        handler(handler_data, 0);
 
201
    }
 
202
 
 
203
    return 1;
 
204
 
 
205
 out_err:
 
206
    opq_unlock(opq);
 
207
    return 0;
 
208
}
 
209
 
 
210
void
 
211
opq_add_block(opq_t *opq)
 
212
{
 
213
    opq_lock(opq);
 
214
    opq->blocked = 1;
 
215
    opq_unlock(opq);
 
216
}
 
217
 
 
218
void
 
219
opq_op_done(opq_t *opq)
 
220
{
 
221
    ilist_iter_t   iter;
 
222
    opq_elem_t     *elem;
 
223
    opq_elem_t     *list = NULL;
 
224
    opq_elem_t     *next;
 
225
    opq_elem_t     **list_end = &list;
 
226
    opq_done_cb    done_handler;
 
227
    void           *done_data;
 
228
 
 
229
    /* First check for done handlers. */
 
230
    opq_lock(opq);
 
231
    ilist_init_iter(&iter, opq->ops);
 
232
    ilist_first(&iter);
 
233
    elem = ilist_get(&iter);
 
234
    while (elem && (!elem->block)) {
 
235
        ilist_delete(&iter);
 
236
        elem->next = NULL;
 
237
        *list_end = elem;
 
238
        list_end = &(elem->next);
 
239
        elem = ilist_get(&iter);
 
240
    }
 
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. */
 
246
        opq_unlock(opq);
 
247
 
 
248
        if (done_handler)
 
249
            done_handler(done_data, 0);
 
250
        while (list) {
 
251
            next = list->next;
 
252
            list->done(list->done_data, 0);
 
253
            ipmi_mem_free(list);
 
254
            list = next;
 
255
        }
 
256
 
 
257
        opq_lock(opq);
 
258
        /* During the time we were unlocked, handlers may have been
 
259
           added. */
 
260
        ilist_first(&iter);
 
261
        elem = ilist_get(&iter);
 
262
    }
 
263
    if (elem) {
 
264
        ilist_delete(&iter);
 
265
        opq->done_handler = elem->done;
 
266
        opq->done_data = elem->done_data;
 
267
        opq_unlock(opq);
 
268
        elem->handler(elem->handler_data, 0);
 
269
        ipmi_mem_free(elem);
 
270
    } else {
 
271
        /* The list is empty. */
 
272
        opq->in_handler = 0;
 
273
        opq_unlock(opq);
 
274
    }
 
275
}
 
276
 
 
277
int
 
278
opq_stuff_in_progress(opq_t *opq)
 
279
{
 
280
    return opq->in_handler;
 
281
}