diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2013-06-25 01:27:07 -0400 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2014-06-07 05:30:42 -0400 |
commit | 2edfb17682026b6a1efcd67d4ec9bb3f75b02d3b (patch) | |
tree | b49af42cb00ace1be3c3ab1920688db9c08933c6 /litmus/bheap.c | |
parent | 493f1cfd648d8b50276b61532bea8b862308a4a1 (diff) |
Add LITMUS^RT core implementation
This patch adds the core of LITMUS^RT:
- library functionality (heaps, rt_domain, prioritization, etc.)
- budget enforcement logic
- job management
- system call backends
- virtual devices (control page, etc.)
- scheduler plugin API (and dummy plugin)
This code compiles, but is not yet integrated with the rest of Linux.
Diffstat (limited to 'litmus/bheap.c')
-rw-r--r-- | litmus/bheap.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/litmus/bheap.c b/litmus/bheap.c new file mode 100644 index 000000000000..2707e0122b6d --- /dev/null +++ b/litmus/bheap.c | |||
@@ -0,0 +1,316 @@ | |||
1 | #include <linux/bug.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <litmus/bheap.h> | ||
4 | |||
5 | void bheap_init(struct bheap* heap) | ||
6 | { | ||
7 | heap->head = NULL; | ||
8 | heap->min = NULL; | ||
9 | } | ||
10 | |||
11 | void bheap_node_init(struct bheap_node** _h, void* value) | ||
12 | { | ||
13 | struct bheap_node* h = *_h; | ||
14 | h->parent = NULL; | ||
15 | h->next = NULL; | ||
16 | h->child = NULL; | ||
17 | h->degree = NOT_IN_HEAP; | ||
18 | h->value = value; | ||
19 | h->ref = _h; | ||
20 | } | ||
21 | |||
22 | |||
23 | /* make child a subtree of root */ | ||
24 | static void __bheap_link(struct bheap_node* root, | ||
25 | struct bheap_node* child) | ||
26 | { | ||
27 | child->parent = root; | ||
28 | child->next = root->child; | ||
29 | root->child = child; | ||
30 | root->degree++; | ||
31 | } | ||
32 | |||
33 | /* merge root lists */ | ||
34 | static struct bheap_node* __bheap_merge(struct bheap_node* a, | ||
35 | struct bheap_node* b) | ||
36 | { | ||
37 | struct bheap_node* head = NULL; | ||
38 | struct bheap_node** pos = &head; | ||
39 | |||
40 | while (a && b) { | ||
41 | if (a->degree < b->degree) { | ||
42 | *pos = a; | ||
43 | a = a->next; | ||
44 | } else { | ||
45 | *pos = b; | ||
46 | b = b->next; | ||
47 | } | ||
48 | pos = &(*pos)->next; | ||
49 | } | ||
50 | if (a) | ||
51 | *pos = a; | ||
52 | else | ||
53 | *pos = b; | ||
54 | return head; | ||
55 | } | ||
56 | |||
57 | /* reverse a linked list of nodes. also clears parent pointer */ | ||
58 | static struct bheap_node* __bheap_reverse(struct bheap_node* h) | ||
59 | { | ||
60 | struct bheap_node* tail = NULL; | ||
61 | struct bheap_node* next; | ||
62 | |||
63 | if (!h) | ||
64 | return h; | ||
65 | |||
66 | h->parent = NULL; | ||
67 | while (h->next) { | ||
68 | next = h->next; | ||
69 | h->next = tail; | ||
70 | tail = h; | ||
71 | h = next; | ||
72 | h->parent = NULL; | ||
73 | } | ||
74 | h->next = tail; | ||
75 | return h; | ||
76 | } | ||
77 | |||
78 | static void __bheap_min(bheap_prio_t higher_prio, struct bheap* heap, | ||
79 | struct bheap_node** prev, struct bheap_node** node) | ||
80 | { | ||
81 | struct bheap_node *_prev, *cur; | ||
82 | *prev = NULL; | ||
83 | |||
84 | if (!heap->head) { | ||
85 | *node = NULL; | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | *node = heap->head; | ||
90 | _prev = heap->head; | ||
91 | cur = heap->head->next; | ||
92 | while (cur) { | ||
93 | if (higher_prio(cur, *node)) { | ||
94 | *node = cur; | ||
95 | *prev = _prev; | ||
96 | } | ||
97 | _prev = cur; | ||
98 | cur = cur->next; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static void __bheap_union(bheap_prio_t higher_prio, struct bheap* heap, | ||
103 | struct bheap_node* h2) | ||
104 | { | ||
105 | struct bheap_node* h1; | ||
106 | struct bheap_node *prev, *x, *next; | ||
107 | if (!h2) | ||
108 | return; | ||
109 | h1 = heap->head; | ||
110 | if (!h1) { | ||
111 | heap->head = h2; | ||
112 | return; | ||
113 | } | ||
114 | h1 = __bheap_merge(h1, h2); | ||
115 | prev = NULL; | ||
116 | x = h1; | ||
117 | next = x->next; | ||
118 | while (next) { | ||
119 | if (x->degree != next->degree || | ||
120 | (next->next && next->next->degree == x->degree)) { | ||
121 | /* nothing to do, advance */ | ||
122 | prev = x; | ||
123 | x = next; | ||
124 | } else if (higher_prio(x, next)) { | ||
125 | /* x becomes the root of next */ | ||
126 | x->next = next->next; | ||
127 | __bheap_link(x, next); | ||
128 | } else { | ||
129 | /* next becomes the root of x */ | ||
130 | if (prev) | ||
131 | prev->next = next; | ||
132 | else | ||
133 | h1 = next; | ||
134 | __bheap_link(next, x); | ||
135 | x = next; | ||
136 | } | ||
137 | next = x->next; | ||
138 | } | ||
139 | heap->head = h1; | ||
140 | } | ||
141 | |||
142 | static struct bheap_node* __bheap_extract_min(bheap_prio_t higher_prio, | ||
143 | struct bheap* heap) | ||
144 | { | ||
145 | struct bheap_node *prev, *node; | ||
146 | __bheap_min(higher_prio, heap, &prev, &node); | ||
147 | if (!node) | ||
148 | return NULL; | ||
149 | if (prev) | ||
150 | prev->next = node->next; | ||
151 | else | ||
152 | heap->head = node->next; | ||
153 | __bheap_union(higher_prio, heap, __bheap_reverse(node->child)); | ||
154 | return node; | ||
155 | } | ||
156 | |||
157 | /* insert (and reinitialize) a node into the heap */ | ||
158 | void bheap_insert(bheap_prio_t higher_prio, struct bheap* heap, | ||
159 | struct bheap_node* node) | ||
160 | { | ||
161 | struct bheap_node *min; | ||
162 | node->child = NULL; | ||
163 | node->parent = NULL; | ||
164 | node->next = NULL; | ||
165 | node->degree = 0; | ||
166 | if (heap->min && higher_prio(node, heap->min)) { | ||
167 | /* swap min cache */ | ||
168 | min = heap->min; | ||
169 | min->child = NULL; | ||
170 | min->parent = NULL; | ||
171 | min->next = NULL; | ||
172 | min->degree = 0; | ||
173 | __bheap_union(higher_prio, heap, min); | ||
174 | heap->min = node; | ||
175 | } else | ||
176 | __bheap_union(higher_prio, heap, node); | ||
177 | } | ||
178 | |||
179 | void bheap_uncache_min(bheap_prio_t higher_prio, struct bheap* heap) | ||
180 | { | ||
181 | struct bheap_node* min; | ||
182 | if (heap->min) { | ||
183 | min = heap->min; | ||
184 | heap->min = NULL; | ||
185 | bheap_insert(higher_prio, heap, min); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | /* merge addition into target */ | ||
190 | void bheap_union(bheap_prio_t higher_prio, | ||
191 | struct bheap* target, struct bheap* addition) | ||
192 | { | ||
193 | /* first insert any cached minima, if necessary */ | ||
194 | bheap_uncache_min(higher_prio, target); | ||
195 | bheap_uncache_min(higher_prio, addition); | ||
196 | __bheap_union(higher_prio, target, addition->head); | ||
197 | /* this is a destructive merge */ | ||
198 | addition->head = NULL; | ||
199 | } | ||
200 | |||
201 | struct bheap_node* bheap_peek(bheap_prio_t higher_prio, | ||
202 | struct bheap* heap) | ||
203 | { | ||
204 | if (!heap->min) | ||
205 | heap->min = __bheap_extract_min(higher_prio, heap); | ||
206 | return heap->min; | ||
207 | } | ||
208 | |||
209 | struct bheap_node* bheap_take(bheap_prio_t higher_prio, | ||
210 | struct bheap* heap) | ||
211 | { | ||
212 | struct bheap_node *node; | ||
213 | if (!heap->min) | ||
214 | heap->min = __bheap_extract_min(higher_prio, heap); | ||
215 | node = heap->min; | ||
216 | heap->min = NULL; | ||
217 | if (node) | ||
218 | node->degree = NOT_IN_HEAP; | ||
219 | return node; | ||
220 | } | ||
221 | |||
222 | int bheap_decrease(bheap_prio_t higher_prio, struct bheap_node* node) | ||
223 | { | ||
224 | struct bheap_node *parent; | ||
225 | struct bheap_node** tmp_ref; | ||
226 | void* tmp; | ||
227 | |||
228 | /* bubble up */ | ||
229 | parent = node->parent; | ||
230 | while (parent && higher_prio(node, parent)) { | ||
231 | /* swap parent and node */ | ||
232 | tmp = parent->value; | ||
233 | parent->value = node->value; | ||
234 | node->value = tmp; | ||
235 | /* swap references */ | ||
236 | *(parent->ref) = node; | ||
237 | *(node->ref) = parent; | ||
238 | tmp_ref = parent->ref; | ||
239 | parent->ref = node->ref; | ||
240 | node->ref = tmp_ref; | ||
241 | /* step up */ | ||
242 | node = parent; | ||
243 | parent = node->parent; | ||
244 | } | ||
245 | |||
246 | return parent != NULL; | ||
247 | } | ||
248 | |||
249 | void bheap_delete(bheap_prio_t higher_prio, struct bheap* heap, | ||
250 | struct bheap_node* node) | ||
251 | { | ||
252 | struct bheap_node *parent, *prev, *pos; | ||
253 | struct bheap_node** tmp_ref; | ||
254 | void* tmp; | ||
255 | |||
256 | if (heap->min != node) { | ||
257 | /* bubble up */ | ||
258 | parent = node->parent; | ||
259 | while (parent) { | ||
260 | /* swap parent and node */ | ||
261 | tmp = parent->value; | ||
262 | parent->value = node->value; | ||
263 | node->value = tmp; | ||
264 | /* swap references */ | ||
265 | *(parent->ref) = node; | ||
266 | *(node->ref) = parent; | ||
267 | tmp_ref = parent->ref; | ||
268 | parent->ref = node->ref; | ||
269 | node->ref = tmp_ref; | ||
270 | /* step up */ | ||
271 | node = parent; | ||
272 | parent = node->parent; | ||
273 | } | ||
274 | /* now delete: | ||
275 | * first find prev */ | ||
276 | prev = NULL; | ||
277 | pos = heap->head; | ||
278 | while (pos != node) { | ||
279 | BUG_ON(!pos); /* fell off the list -> deleted from wrong heap */ | ||
280 | prev = pos; | ||
281 | pos = pos->next; | ||
282 | } | ||
283 | /* we have prev, now remove node */ | ||
284 | if (prev) | ||
285 | prev->next = node->next; | ||
286 | else | ||
287 | heap->head = node->next; | ||
288 | __bheap_union(higher_prio, heap, __bheap_reverse(node->child)); | ||
289 | } else | ||
290 | heap->min = NULL; | ||
291 | node->degree = NOT_IN_HEAP; | ||
292 | } | ||
293 | |||
294 | /* allocate a heap node for value and insert into the heap */ | ||
295 | int bheap_add(bheap_prio_t higher_prio, struct bheap* heap, | ||
296 | void* value, int gfp_flags) | ||
297 | { | ||
298 | struct bheap_node* hn = bheap_node_alloc(gfp_flags); | ||
299 | if (likely(hn)) { | ||
300 | bheap_node_init(&hn, value); | ||
301 | bheap_insert(higher_prio, heap, hn); | ||
302 | } | ||
303 | return hn != NULL; | ||
304 | } | ||
305 | |||
306 | void* bheap_take_del(bheap_prio_t higher_prio, | ||
307 | struct bheap* heap) | ||
308 | { | ||
309 | struct bheap_node* hn = bheap_take(higher_prio, heap); | ||
310 | void* ret = NULL; | ||
311 | if (hn) { | ||
312 | ret = hn->value; | ||
313 | bheap_node_free(hn); | ||
314 | } | ||
315 | return ret; | ||
316 | } | ||