2 * Copyright 2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and
30 * documentation are those of the authors and should not be
31 * interpreted as representing official policies, either expressed
32 * or implied, of GRNET S.A.
35 #include <xtypes/xq.h>
36 #include <xtypes/domain.h>
38 static inline int __snap(xqindex size)
42 return 1 << ((sizeof(size) * 8) - __builtin_clz(size) - 1);
45 void xq_free(struct xq *xq) {
46 xtypes_free((void *)XPTR(&xq->queue));
47 memset(xq, 0, sizeof(struct xq));
50 void xq_init_empty(struct xq *xq, xqindex size, void *mem)
54 XPTRSET(&xq->queue, mem);
55 xq->size = __snap(size);
56 xlock_release(&xq->lock);
59 void xq_init_map(struct xq *xq,
62 xqindex (*mapfn)(xqindex),
65 xqindex t, *qmem = mem;
68 XPTRSET(&xq->queue, qmem);
69 xq->size = __snap(size);
70 for (t = 0; t < count; t++)
72 xlock_release(&xq->lock);
75 void xq_init_seq(struct xq *xq, xqindex size, xqindex count, void *mem)
77 xqindex t, *qmem = mem;
80 XPTRSET(&xq->queue, qmem);
81 xq->size = __snap(size);
82 for (t = 0; t < count; t++)
84 xlock_release(&xq->lock);
87 xqindex *xq_alloc_empty(struct xq *xq, xqindex size)
89 xqindex *mem = xtypes_malloc(size * sizeof(xqindex));
92 xq_init_empty(xq, size, mem);
96 xqindex *xq_alloc_map(struct xq *xq,
99 xqindex (*mapfn)(xqindex) )
101 xqindex *mem = xtypes_malloc(size * sizeof(xqindex));
104 xq_init_map(xq, size, count, mapfn, mem);
108 xqindex *xq_alloc_seq(struct xq *xq, xqindex size, xqindex count)
110 xqindex *mem = xtypes_malloc(size * sizeof(xqindex));
113 xq_init_seq(xq, size, count, mem);
117 xqindex xq_size(struct xq *xq)
122 xqindex xq_count(struct xq *xq)
124 return xq->head - xq->tail - 1;
127 xqindex xq_element(struct xq *xq, xqindex index)
129 return XPTR(&xq->queue)[index & (xq->size - 1)];
132 void xq_print(struct xq *xq)
136 XSEGLOG("xq head: %lu, tail: %lu, size: %lu\n",
137 (unsigned long)xq->head,
138 (unsigned long)xq->tail,
139 (unsigned long)xq->size);
145 XSEGLOG( "%lu %lu\n",
147 (unsigned long)xq_element(xq, i) );
152 xqindex __xq_append_head_idx(struct xq *xq, xqindex nr)
154 xqindex head = xq->head;
155 xq->head = head + nr;
160 xqindex xq_append_heads(struct xq *xq,
164 xqindex i, mask, head;
165 xqindex serial = xlock_acquire(&xq->lock, nr);
167 if (!(xq_count(xq) + nr <= xq->size)) {
173 head = __xq_append_head_idx(xq, nr);
174 for (i = 0; i < nr; i++)
175 XPTR(&xq->queue)[(head + i) & mask] = heads[i];
177 xlock_release(&xq->lock);
182 xqindex __xq_append_head(struct xq *xq, xqindex xqi)
184 if (xq_count(xq) >= xq->size) {
187 XPTR(&xq->queue)[__xq_append_head_idx(xq, 1) & (xq->size -1)] = xqi;
191 xqindex xq_append_head(struct xq *xq, xqindex xqi, unsigned long who)
194 xlock_acquire(&xq->lock, who);
195 serial = __xq_append_head(xq, xqi);
196 xlock_release(&xq->lock);
200 xqindex __xq_pop_head_idx(struct xq *xq, xqindex nr)
202 xqindex head = xq->head - nr;
208 xqindex xq_pop_heads(struct xq *xq,
212 xqindex i, mask, head;
213 xqindex serial = xlock_acquire(&xq->lock, nr);
215 if (xq_count(xq) < nr) {
221 head = __xq_pop_head_idx(xq, nr);
222 for (i = 0; i < nr; i++)
223 heads[i] = XPTR(&xq->queue)[(head - i) & mask];
225 xlock_release(&xq->lock);
230 xqindex __xq_pop_head(struct xq *xq)
232 xqindex value = Noneidx;
235 return XPTR(&xq->queue)[__xq_pop_head_idx(xq, 1) & (xq->size -1)];
238 xqindex xq_pop_head(struct xq *xq, unsigned long who)
240 xqindex value = Noneidx;
241 (void)xlock_acquire(&xq->lock, who);
242 value = __xq_pop_head(xq);
243 xlock_release(&xq->lock);
247 xqindex __xq_peek_head_idx(struct xq *xq, xqindex nr)
249 xqindex head = xq->head - nr;
253 xqindex __xq_peek_head(struct xq *xq)
257 return XPTR(&xq->queue)[__xq_peek_head_idx(xq, 1) & (xq->size -1)];
260 xqindex xq_peek_head(struct xq *xq, unsigned long who)
263 (void)xlock_acquire(&xq->lock, who);
264 value = __xq_peek_head(xq);
265 xlock_release(&xq->lock);
269 xqindex __xq_peek_tail_idx(struct xq *xq, xqindex nr)
271 xqindex tail = xq->tail + nr;
275 xqindex __xq_peek_tail(struct xq *xq)
279 return XPTR(&xq->queue)[__xq_peek_tail_idx(xq, 1) & (xq->size -1)];
282 xqindex xq_peek_tail(struct xq *xq, unsigned long who)
285 (void)xlock_acquire(&xq->lock, who);
286 value = __xq_peek_tail(xq);
287 xlock_release(&xq->lock);
291 xqindex __xq_append_tail_idx(struct xq *xq, xqindex nr)
293 xqindex tail = xq->tail - nr;
299 xqindex xq_append_tails(struct xq *xq,
303 xqindex i, mask, tail;
304 xqindex serial = xlock_acquire(&xq->lock, nr);
306 if (!(xq_count(xq) + nr <= xq->size)) {
312 tail = __xq_append_tail_idx(xq, nr) + nr -1;
313 for (i = 0; i < nr; i++)
314 XPTR(&xq->queue)[(tail - i) & mask] = tails[i];
316 xlock_release(&xq->lock);
321 xqindex __xq_append_tail(struct xq *xq, xqindex xqi)
323 if (!(xq_count(xq) + 1 <= xq->size)) {
326 XPTR(&xq->queue)[__xq_append_tail_idx(xq, 1) & (xq->size -1)] = xqi;
330 xqindex xq_append_tail(struct xq *xq, xqindex xqi, unsigned long who)
332 xqindex serial = Noneidx;
333 xlock_acquire(&xq->lock, who);
334 serial =__xq_append_tail(xq, xqi);
335 xlock_release(&xq->lock);
339 xqindex __xq_pop_tail_idx(struct xq *xq, xqindex nr)
341 xqindex tail = xq->tail;
342 xq->tail = tail + nr;
347 xqindex xq_pop_tails(struct xq *xq, xqindex nr, xqindex *tails)
349 xqindex i, mask, tail;
350 xqindex serial = xlock_acquire(&xq->lock, nr);
352 if (xq_count(xq) < nr) {
358 tail = __xq_pop_tail_idx(xq, nr);
359 for (i = 0; i < nr; i++)
360 tails[i] = XPTR(&xq->queue)[(tail + i) & mask];
362 xlock_release(&xq->lock);
367 xqindex __xq_pop_tail(struct xq *xq)
371 return XPTR(&xq->queue)[__xq_pop_tail_idx(xq, 1) & (xq->size -1)];
374 xqindex xq_pop_tail(struct xq *xq, unsigned long who)
377 (void)xlock_acquire(&xq->lock, who);
378 value = __xq_pop_tail(xq);
379 xlock_release(&xq->lock);
383 int xq_head_to_tail(struct xq *headq, struct xq *tailq, xqindex nr, unsigned long who)
385 xqindex head, tail, hmask, tmask, *hq, *tq, i, ret = -1;
387 if (headq >= tailq) {
388 xlock_acquire(&headq->lock, who);
389 xlock_acquire(&tailq->lock, who);
391 xlock_acquire(&tailq->lock, who);
392 xlock_acquire(&headq->lock, who);
395 if (xq_count(headq) < nr || xq_count(tailq) + nr > tailq->size)
398 hmask = headq->size -1;
399 tmask = tailq->size -1;
400 head = __xq_pop_head_idx(headq, nr);
401 tail = __xq_append_tail_idx(tailq, nr);
402 hq = XPTR(&headq->queue);
403 tq = XPTR(&tailq->queue);
405 for (i = 0; i < nr; i++)
406 tq[(tail + i) & tmask] = hq[(head + i) & hmask];
410 xlock_release(&headq->lock);
411 xlock_release(&tailq->lock);
415 int __xq_check(struct xq *xq, xqindex idx)
418 for (i = xq->tail + 1; i != xq->head ; i++) {
419 val = XPTR(&xq->queue)[i & (xq->size -1)];
426 int xq_check(struct xq *xq, xqindex idx, unsigned long who)
429 xlock_acquire(&xq->lock, who);
430 r = __xq_check(xq, idx);
431 xlock_release(&xq->lock);
435 xqindex __xq_resize(struct xq *xq, struct xq *newxq)
437 xqindex i, mask, mask_new, head, tail, val;
438 xqindex nr = xq_count(xq);
440 if (nr > newxq->size) {
445 mask_new = newxq->size -1;
446 head = __xq_peek_head_idx(xq, nr);
447 tail = __xq_append_tail_idx(newxq, nr) + nr -1;
448 for (i = 0; i < nr; i++) {
449 val = XPTR(&xq->queue)[(head + i) & mask];
450 XPTR(&newxq->queue)[(tail - i) & mask_new] = val;
456 xqindex xq_resize(struct xq *xq, struct xq *newxq, unsigned long who)
459 xlock_acquire(&xq->lock, who);
460 xlock_acquire(&newxq->lock, who);
461 r = __xq_resize(xq, newxq);
462 xlock_release(&newxq->lock);
463 xlock_release(&xq->lock);
468 #include <linux/module.h>
469 #include <xtypes/xq_exports.h>