Xenomai API
2.5.6.1
|
00001 /* 00002 * Copyright (C) 2006 Gilles Chanteperdrix <[email protected]> 00003 * 00004 * Xenomai is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published 00006 * by the Free Software Foundation; either version 2 of the License, 00007 * or (at your option) any later version. 00008 * 00009 * Xenomai is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with Xenomai; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00017 * 02111-1307, USA. 00018 */ 00019 00020 #ifndef _XENO_NUCLEUS_BHEAP_H 00021 #define _XENO_NUCLEUS_BHEAP_H 00022 00023 #include <nucleus/compiler.h> 00024 00025 /* debug support */ 00026 #include <nucleus/assert.h> 00027 00028 /* Priority queue implementation, using a binary heap. */ 00029 00030 typedef unsigned long long bheap_key_t; 00031 00032 typedef struct bheaph { 00033 bheap_key_t key; 00034 unsigned prio; 00035 unsigned pos; 00036 } bheaph_t; 00037 00038 #define bheaph_init(holder) do { } while (0) 00039 #define bheaph_key(holder) ((holder)->key) 00040 #define bheaph_prio(holder) ((holder)->prio) 00041 #define bheaph_pos(holder) ((holder)->pos) 00042 #define bheaph_lt(h1, h2) ((long long) ((h1)->key - (h2)->key) < 0 || \ 00043 ((h1)->key == (h2)->key && \ 00044 (h1)->prio > (h2)->prio)) 00045 00046 typedef struct bheap { 00047 unsigned sz; 00048 unsigned last; 00049 bheaph_t *elems[1]; /* only padding, indexing starts at 1 */ 00050 } bheap_t; 00051 00052 #define DECLARE_BHEAP_CONTAINER(name, sz) \ 00053 struct { \ 00054 bheap_t bheap; \ 00055 bheaph_t *elems[sz]; \ 00056 } name 00057 00058 /* Check the binary heap invariant. */ 00059 static inline int bheap_ordered(bheap_t *heap) 00060 { 00061 unsigned i; 00062 for (i = 2; i < heap->last; i++) 00063 if (bheaph_lt(heap->elems[i], heap->elems[i / 2])) 00064 return 0; 00065 return 1; 00066 } 00067 00068 #define BHEAP_CHECK(heap) \ 00069 XENO_BUGON(QUEUES, ((heap)->sz == 0) || !bheap_ordered(heap)) 00070 00071 #define bheap_gethead(heap) \ 00072 ({ \ 00073 bheap_t *_bheap = &(heap)->bheap; \ 00074 BHEAP_CHECK(_bheap); \ 00075 __internal_bheap_gethead(_bheap); \ 00076 }) 00077 00078 static inline bheaph_t *__internal_bheap_gethead(bheap_t *heap) 00079 { 00080 if (heap->last == 1) 00081 return NULL; 00082 00083 return heap->elems[1]; 00084 } 00085 00086 #define bheap_next(heap, holder) \ 00087 ({ \ 00088 bheap_t *_bheap = &(heap)->bheap; \ 00089 BHEAP_CHECK(_bheap); \ 00090 __internal_bheap_next(_bheap, holder); \ 00091 }) 00092 00093 static inline bheaph_t *__internal_bheap_next(bheap_t *heap, bheaph_t *holder) 00094 { 00095 unsigned pos; 00096 00097 if (unlikely(bheaph_pos(holder) >= heap->last 00098 || heap->elems[bheaph_pos(holder)] != holder)) 00099 return (bheaph_t *) ERR_PTR(-EINVAL); 00100 00101 pos = bheaph_pos(holder) + 1; 00102 00103 return likely(pos < heap->last) ? heap->elems[pos] : NULL; 00104 } 00105 00106 static inline bheaph_t *bheaph_parent(bheap_t *heap, bheaph_t *holder) 00107 { 00108 const unsigned pos = holder->pos; 00109 00110 return likely(pos > 1) ? heap->elems[pos / 2] : NULL; 00111 } 00112 00113 static inline bheaph_t *bheaph_child(bheap_t *heap, bheaph_t *holder, int side) 00114 { 00115 const unsigned pos = 2 * holder->pos + side; 00116 00117 return likely(pos < heap->last) ? heap->elems[pos] : NULL; 00118 } 00119 00120 #define bheap_init(heap, sz) __internal_bheap_init(&(heap)->bheap, sz) 00121 00122 static inline void __internal_bheap_init(bheap_t *heap, unsigned sz) 00123 { 00124 heap->sz = sz; 00125 heap->last = 1; 00126 } 00127 00128 #define bheap_destroy(heap) __internal_bheap_destroy(&(heap)->bheap) 00129 00130 static inline void __internal_bheap_destroy(bheap_t *heap) 00131 { 00132 heap->sz = 0; 00133 heap->last = 1; 00134 } 00135 00136 static inline void bheap_swap(bheap_t *heap, bheaph_t *h1, bheaph_t *h2) 00137 { 00138 const unsigned pos2 = bheaph_pos(h2); 00139 00140 heap->elems[bheaph_pos(h1)] = h2; 00141 bheaph_pos(h2) = bheaph_pos(h1); 00142 heap->elems[pos2] = h1; 00143 bheaph_pos(h1) = pos2; 00144 } 00145 00146 static inline void bheap_up(bheap_t *heap, bheaph_t *holder) 00147 { 00148 bheaph_t *parent; 00149 00150 while ((parent = bheaph_parent(heap, holder)) && bheaph_lt(holder, parent)) 00151 bheap_swap(heap, holder, parent); 00152 } 00153 00154 static inline void bheap_down(bheap_t *heap, bheaph_t *holder) 00155 { 00156 bheaph_t *left, *right, *minchild; 00157 00158 for (;;) { 00159 left = bheaph_child(heap, holder, 0); 00160 right = bheaph_child(heap, holder, 1); 00161 00162 if (left && right) 00163 minchild = bheaph_lt(left, right) ? left : right; 00164 else 00165 minchild = left ?: right; 00166 00167 if (!minchild || bheaph_lt(holder, minchild)) 00168 break; 00169 00170 bheap_swap(heap, minchild, holder); 00171 } 00172 } 00173 00174 #define bheap_insert(heap, holder) \ 00175 ({ \ 00176 bheap_t *_bheap = &(heap)->bheap; \ 00177 BHEAP_CHECK(_bheap); \ 00178 __internal_bheap_insert(_bheap, holder); \ 00179 }) 00180 00181 static inline int __internal_bheap_insert(bheap_t *heap, bheaph_t *holder) 00182 { 00183 if (heap->last == heap->sz + 1) 00184 return EBUSY; 00185 00186 heap->elems[heap->last] = holder; 00187 bheaph_pos(holder) = heap->last; 00188 ++heap->last; 00189 bheap_up(heap, holder); 00190 return 0; 00191 } 00192 00193 #define bheap_delete(heap, holder) \ 00194 ({ \ 00195 bheap_t *_bheap = &(heap)->bheap; \ 00196 BHEAP_CHECK(_bheap); \ 00197 __internal_bheap_delete(_bheap, holder); \ 00198 }) 00199 00200 static inline int __internal_bheap_delete(bheap_t *heap, bheaph_t *holder) 00201 { 00202 bheaph_t *lasth; 00203 00204 if (unlikely(bheaph_pos(holder) >= heap->last 00205 || heap->elems[bheaph_pos(holder)] != holder)) 00206 return EINVAL; 00207 00208 --heap->last; 00209 if (heap->last != bheaph_pos(holder)) { 00210 bheaph_t *parent; 00211 lasth = heap->elems[heap->last]; 00212 heap->elems[bheaph_pos(holder)] = lasth; 00213 bheaph_pos(lasth) = bheaph_pos(holder); 00214 if ((parent = bheaph_parent(heap, lasth)) && bheaph_lt(lasth, parent)) 00215 bheap_up(heap, lasth); 00216 else 00217 bheap_down(heap, lasth); 00218 } 00219 00220 return 0; 00221 } 00222 00223 #define bheap_get(heap) \ 00224 ({ \ 00225 bheap_t *_bheap = &(heap)->bheap; \ 00226 BHEAP_CHECK(_bheap); \ 00227 __internal_bheap_get(_bheap, holder); \ 00228 }) 00229 00230 static inline bheaph_t *__internal_bheap_get(bheap_t *heap) 00231 { 00232 bheaph_t *holder = __internal_bheap_gethead(heap); 00233 00234 if (!holder) 00235 return NULL; 00236 00237 __internal_bheap_delete(heap, holder); 00238 00239 return holder; 00240 } 00241 00242 #endif /* _XENO_NUCLEUS_BHEAP_H */