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 #define BHEAP_CHECK(heap) XENO_BUGON(QUEUES, ((heap)->sz == 0))
00063
00064 #define bheap_gethead(heap) \
00065 ({ \
00066 bheap_t *_bheap = &(heap)->bheap; \
00067 BHEAP_CHECK(_bheap); \
00068 __internal_bheap_gethead(_bheap); \
00069 })
00070
00071 static inline bheaph_t *__internal_bheap_gethead(bheap_t *heap)
00072 {
00073 if (heap->last == 1)
00074 return NULL;
00075
00076 return heap->elems[1];
00077 }
00078
00079 static inline bheaph_t *bheaph_parent(bheap_t *heap, bheaph_t *holder)
00080 {
00081 const unsigned pos = holder->pos;
00082
00083 return likely(pos > 1) ? heap->elems[pos / 2] : NULL;
00084 }
00085
00086 static inline bheaph_t *bheaph_child(bheap_t *heap, bheaph_t *holder, int side)
00087 {
00088 const unsigned pos = 2 * holder->pos + side;
00089
00090 return likely(pos < heap->last) ? heap->elems[pos] : NULL;
00091 }
00092
00093 #define bheap_init(heap, sz) __internal_bheap_init(&(heap)->bheap, sz)
00094
00095 static inline void __internal_bheap_init(bheap_t *heap, unsigned sz)
00096 {
00097 heap->sz = sz;
00098 heap->last = 1;
00099 }
00100
00101 #define bheap_destroy(heap) __internal_bheap_destroy(&(heap)->bheap)
00102
00103 static inline void __internal_bheap_destroy(bheap_t *heap)
00104 {
00105 heap->sz = 0;
00106 heap->last = 1;
00107 }
00108
00109 static inline void bheap_swap(bheap_t *heap, bheaph_t *h1, bheaph_t *h2)
00110 {
00111 const unsigned pos2 = bheaph_pos(h2);
00112
00113 heap->elems[bheaph_pos(h1)] = h2;
00114 bheaph_pos(h2) = bheaph_pos(h1);
00115 heap->elems[pos2] = h1;
00116 bheaph_pos(h1) = pos2;
00117 }
00118
00119 static inline void bheap_up(bheap_t *heap, bheaph_t *holder)
00120 {
00121 bheaph_t *parent;
00122
00123 while ((parent = bheaph_parent(heap, holder)) && bheaph_lt(holder, parent))
00124 bheap_swap(heap, holder, parent);
00125 }
00126
00127 static inline void bheap_down(bheap_t *heap, bheaph_t *holder)
00128 {
00129 bheaph_t *left, *right, *minchild;
00130
00131 for (;;) {
00132 left = bheaph_child(heap, holder, 0);
00133 right = bheaph_child(heap, holder, 1);
00134
00135 if (left && right)
00136 minchild = bheaph_lt(left, right) ? left : right;
00137 else
00138 minchild = left ?: right;
00139
00140 if (!minchild || bheaph_lt(holder, minchild))
00141 break;
00142
00143 bheap_swap(heap, minchild, holder);
00144 }
00145 }
00146
00147 #define bheap_insert(heap, holder) \
00148 ({ \
00149 bheap_t *_bheap = &(heap)->bheap; \
00150 BHEAP_CHECK(_bheap); \
00151 __internal_bheap_insert(_bheap, holder); \
00152 })
00153
00154 static inline int __internal_bheap_insert(bheap_t *heap, bheaph_t *holder)
00155 {
00156 if (heap->last == heap->sz + 1)
00157 return EBUSY;
00158
00159 heap->elems[heap->last] = holder;
00160 bheaph_pos(holder) = heap->last;
00161 ++heap->last;
00162 bheap_up(heap, holder);
00163 return 0;
00164 }
00165
00166 #define bheap_delete(heap, holder) \
00167 ({ \
00168 bheap_t *_bheap = &(heap)->bheap; \
00169 BHEAP_CHECK(_bheap); \
00170 __internal_bheap_delete(_bheap, holder); \
00171 })
00172
00173 static inline int __internal_bheap_delete(bheap_t *heap, bheaph_t *holder)
00174 {
00175 bheaph_t *lasth;
00176
00177 if (bheaph_pos(holder) >= heap->last)
00178 return EINVAL;
00179
00180 --heap->last;
00181 if (heap->last != bheaph_pos(holder)) {
00182 lasth = heap->elems[heap->last];
00183 heap->elems[bheaph_pos(holder)] = lasth;
00184 bheaph_pos(lasth) = bheaph_pos(holder);
00185 bheap_down(heap, lasth);
00186 }
00187
00188 return 0;
00189 }
00190
00191 #define bheap_get(heap) \
00192 ({ \
00193 bheap_t *_bheap = &(heap)->bheap; \
00194 BHEAP_CHECK(_bheap); \
00195 __internal_bheap_get(_bheap, holder); \
00196 })
00197
00198 static inline bheaph_t *__internal_bheap_get(bheap_t *heap)
00199 {
00200 bheaph_t *holder = __internal_bheap_gethead(heap);
00201
00202 if (!holder)
00203 return NULL;
00204
00205 __internal_bheap_delete(heap, holder);
00206
00207 return holder;
00208 }
00209
00210 #endif