aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/reservations/ext_reservation.c
blob: 6b4889c40bca76517bf903189538dd3a5f2678d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <linux/mm.h>
#include <litmus/litmus.h>
#include <litmus/bheap.h>
#include <litmus/rt_domain.h>
#include <litmus/reservations/ext_reservation.h>

struct release_heap* release_heap_alloc(int gfp_flags);
void release_heap_free(struct release_heap* rh);

int higher_res_prio(struct reservation* first,
		    struct reservation* second)
{
	struct reservation *first_task = first;
	struct reservation *second_task = second;

	/* There is no point in comparing a reservation to itself. */
	if (first && first == second) {
		return 0;
	}

	/* check for NULL reservations */
	if (!first || !second)
		return first && !second;

#ifdef CONFIG_LITMUS_LOCKING

	// SOMEWHAT HACKY -- guarantee that a non-preemptive reservation
	// is higher-priority than any other; fall back to regular
	// priority-checking if both are non-preemptive or both are preemptive
	if (first->ops->is_np(first, -1) != second->ops->is_np(second, -1))
		return first->ops->is_np(first, -1);

	/* Check for inherited priorities. Change reservation
	 * used for comparison in such a case.
	 */
	if (unlikely(first->inh_res))
		first_task = first->inh_res;
	if (unlikely(second->inh_res))
		second_task = second->inh_res;

#endif

	if (first_task->priority > second_task->priority) {
		return 1;
	}
	else if (first_task->priority == second_task->priority) {
		/* Tie break by pid */
		if (first_task->id < second_task->id) {
			return 1;
		}
#ifdef CONFIG_LITMUS_LOCKING
		else if (first_task->id == second_task->id) {
			/* If the PIDs are the same then the task with the
				* inherited priority wins.
				*/
			if (!second->inh_res) {
				return 1;
			}
		}
#endif
	}
	return 0; /* fall-through. prio(second_task) > prio(first_task) */
}

void init_ext_reservation(
	struct reservation* res,
	unsigned int id,
	struct reservation_ops* ops)
{
	res->id = id;
	res->ops = ops;
	res->heap_node = bheap_node_alloc(GFP_ATOMIC);
	res->rel_heap = release_heap_alloc(GFP_ATOMIC);
	bheap_node_init(&res->heap_node, res);
	INIT_LIST_HEAD(&res->ln);
	INIT_LIST_HEAD(&res->all_list);
}

void clean_up_ext_reservation(struct reservation* res)
{
	bheap_node_free(res->heap_node);
	release_heap_free(res->rel_heap);
}