00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _XENO_NUCLEUS_BHEAP_H
00021 #define _XENO_NUCLEUS_BHEAP_H
00022
00023 #include <nucleus/compiler.h>
00024
00025
00026 #include <nucleus/assert.h>
00027
00028 #ifndef CONFIG_XENO_OPT_DEBUG_QUEUES
00029 #define CONFIG_XENO_OPT_DEBUG_QUEUES 0
00030 #endif
00031
00032
00033
00034 typedef unsigned long long bheap_key_t;
00035
00036 typedef struct bheaph {
00037 bheap_key_t key;
00038 unsigned prio;
00039 unsigned pos;
00040 } bheaph_t;
00041
00042 #define bheaph_init(holder) do { } while (0)
00043 #define bheaph_key(holder) ((holder)->key)
00044 #define bheaph_prio(holder) ((holder)->prio)
00045 #define bheaph_pos(holder) ((holder)->pos)
00046 #define bheaph_lt(h1, h2) ((h1)->key < (h2)->key || \
00047 ((h1)->key == (h2)->key && \
00048 (h1)->prio > (h2)->prio))
00049
00050 typedef struct bheap {
00051 unsigned sz;
00052 unsigned last;
00053 bheaph_t *elems[1];
00054 } bheap_t;
00055
00056 #define DECLARE_BHEAP_CONTAINER(name, sz) \
00057 struct { \
00058 bheap_t bheap; \
00059 bheaph_t *elems[sz]; \
00060 } name
00061
00062
00063 static inline int bheap_ordered(bheap_t *heap)
00064 {
00065 unsigned i;
00066 for (i = 2; i < heap->last; i++)
00067 if (bheaph_lt(heap->elems[i], heap->elems[i / 2]))
00068 return 0;
00069 return 1;
00070 }
00071
00072 #define BHEAP_CHECK(heap) \
00073 XENO_BUGON(QUEUES, ((heap)->sz == 0) || !bheap_ordered(heap))
00074
00075 #define bheap_gethead(heap) \
00076 ({ \
00077 bheap_t *_bheap = &(heap)->bheap; \
00078 BHEAP_CHECK(_bheap); \
00079 __internal_bheap_gethead(_bheap); \
00080 })
00081
00082 static inline bheaph_t *__internal_bheap_gethead(bheap_t *heap)
00083 {
00084 if (heap->last == 1)
00085 return NULL;
00086
00087 return heap->elems[1];
00088 }
00089
00090 static inline bheaph_t *bheaph_parent(bheap_t *heap, bheaph_t *holder)
00091 {
00092 const unsigned pos = holder->pos;
00093
00094 return likely(pos > 1) ? heap->elems[pos / 2] : NULL;
00095 }
00096
00097 static inline bheaph_t *bheaph_child(bheap_t *heap, bheaph_t *holder, int side)
00098 {
00099 const unsigned pos = 2 * holder->pos + side;
00100
00101 return likely(pos < heap->last) ? heap->elems[pos] : NULL;
00102 }
00103
00104 #define bheap_init(heap, sz) __internal_bheap_init(&(heap)->bheap, sz)
00105
00106 static inline void __internal_bheap_init(bheap_t *heap, unsigned sz)
00107 {
00108 heap->sz = sz;
00109 heap->last = 1;
00110 }
00111
00112 #define bheap_destroy(heap) __internal_bheap_destroy(&(heap)->bheap)
00113
00114 static inline void __internal_bheap_destroy(bheap_t *heap)
00115 {
00116 heap->sz = 0;
00117 heap->last = 1;
00118 }
00119
00120 static inline void bheap_swap(bheap_t *heap, bheaph_t *h1, bheaph_t *h2)
00121 {
00122 const unsigned pos2 = bheaph_pos(h2);
00123
00124 heap->elems[bheaph_pos(h1)] = h2;
00125 bheaph_pos(h2) = bheaph_pos(h1);
00126 heap->elems[pos2] = h1;
00127 bheaph_pos(h1) = pos2;
00128 }
00129
00130 static inline void bheap_up(bheap_t *heap, bheaph_t *holder)
00131 {
00132 bheaph_t *parent;
00133
00134 while ((parent = bheaph_parent(heap, holder)) && bheaph_lt(holder, parent))
00135 bheap_swap(heap, holder, parent);
00136 }
00137
00138 static inline void bheap_down(bheap_t *heap, bheaph_t *holder)
00139 {
00140 bheaph_t *left, *right, *minchild;
00141
00142 for (;;) {
00143 left = bheaph_child(heap, holder, 0);
00144 right = bheaph_child(heap, holder, 1);
00145
00146 if (left && right)
00147 minchild = bheaph_lt(left, right) ? left : right;
00148 else
00149 minchild = left ?: right;
00150
00151 if (!minchild || bheaph_lt(holder, minchild))
00152 break;
00153
00154 bheap_swap(heap, minchild, holder);
00155 }
00156 }
00157
00158 #define bheap_insert(heap, holder) \
00159 ({ \
00160 bheap_t *_bheap = &(heap)->bheap; \
00161 BHEAP_CHECK(_bheap); \
00162 __internal_bheap_insert(_bheap, holder); \
00163 })
00164
00165 static inline int __internal_bheap_insert(bheap_t *heap, bheaph_t *holder)
00166 {
00167 if (heap->last == heap->sz + 1)
00168 return EBUSY;
00169
00170 heap->elems[heap->last] = holder;
00171 bheaph_pos(holder) = heap->last;
00172 ++heap->last;
00173 bheap_up(heap, holder);
00174 return 0;
00175 }
00176
00177 #define bheap_delete(heap, holder) \
00178 ({ \
00179 bheap_t *_bheap = &(heap)->bheap; \
00180 BHEAP_CHECK(_bheap); \
00181 __internal_bheap_delete(_bheap, holder); \
00182 })
00183
00184 static inline int __internal_bheap_delete(bheap_t *heap, bheaph_t *holder)
00185 {
00186 bheaph_t *lasth;
00187
00188 if (bheaph_pos(holder) >= heap->last)
00189 return EINVAL;
00190
00191 --heap->last;
00192 if (heap->last != bheaph_pos(holder)) {
00193 bheaph_t *parent;
00194 lasth = heap->elems[heap->last];
00195 heap->elems[bheaph_pos(holder)] = lasth;
00196 bheaph_pos(lasth) = bheaph_pos(holder);
00197 if ((parent = bheaph_parent(heap, lasth)) && bheaph_lt(lasth, parent))
00198 bheap_up(heap, lasth);
00199 else
00200 bheap_down(heap, lasth);
00201 }
00202
00203 return 0;
00204 }
00205
00206 #define bheap_get(heap) \
00207 ({ \
00208 bheap_t *_bheap = &(heap)->bheap; \
00209 BHEAP_CHECK(_bheap); \
00210 __internal_bheap_get(_bheap, holder); \
00211 })
00212
00213 static inline bheaph_t *__internal_bheap_get(bheap_t *heap)
00214 {
00215 bheaph_t *holder = __internal_bheap_gethead(heap);
00216
00217 if (!holder)
00218 return NULL;
00219
00220 __internal_bheap_delete(heap, holder);
00221
00222 return holder;
00223 }
00224
00225 #endif