aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/litmus/litmus.h27
-rw-r--r--include/litmus/rt_param.h76
-rw-r--r--litmus/Makefile2
-rw-r--r--litmus/pgm.c131
4 files changed, 202 insertions, 34 deletions
diff --git a/include/litmus/litmus.h b/include/litmus/litmus.h
index 0b071fd359f9..683407328f5a 100644
--- a/include/litmus/litmus.h
+++ b/include/litmus/litmus.h
@@ -120,6 +120,33 @@ static inline lt_t litmus_clock(void)
120 120
121void preempt_if_preemptable(struct task_struct* t, int on_cpu); 121void preempt_if_preemptable(struct task_struct* t, int on_cpu);
122 122
123/* PGM macros */
124#define is_pgm(t) (tsk_rt(t)->is_pgm_node)
125#define is_pgm_src(t) \
126 (is_pgm(t) && \
127 tsk_rt(t)->pgm_params.produce != NULL && \
128 tsk_rt(t)->pgm_params.consume == NULL)
129#define is_pgm_sink(t) \
130 (is_pgm(t) && \
131 tsk_rt(t)->pgm_params.produce == NULL && \
132 tsk_rt(t)->pgm_params.consume != NULL)
133#define is_pgm_intermediate(t) \
134 (is_pgm(t) && \
135 tsk_rt(t)->pgm_params.produce != NULL && \
136 tsk_rt(t)->pgm_params.consume != NULL)
137#ifdef CONFIG_PGM
138int is_pgm_satisfied(struct task_struct* t);
139void pgm_produce(struct task_struct* t);
140void pgm_consume(struct task_struct* t);
141int pgm_complete(struct task_struct* t);
142#else
143/* nothing */
144#define is_pgm_satisfied(t)
145#define pgm_produce(t)
146#define pgm_consume(t)
147#define pgm_complete(t)
148#endif
149
123#ifdef CONFIG_LITMUS_LOCKING 150#ifdef CONFIG_LITMUS_LOCKING
124void srp_ceiling_block(void); 151void srp_ceiling_block(void);
125#else 152#else
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index a5d68250eef3..613e9f98294e 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -44,41 +44,7 @@ struct rt_task {
44 44
45 45
46#ifdef CONFIG_PGM 46#ifdef CONFIG_PGM
47
48#define MAX_FAN CONFIG_MAX_PGM_FAN 47#define MAX_FAN CONFIG_MAX_PGM_FAN
49#define FAN_BYTES (((MAX_FAN)/8) + ((MAX_FAN)%8 != 0))
50
51struct pgm_production
52{
53 struct task_struct* child; /* task that receives tokens */
54 int nr_tokens; /* num tokens to generate */
55};
56
57struct pgm_produce
58{
59 int nr_productions; /* num productions/children */
60 struct pgm_production produce[0]; /* array of productions */
61};
62
63struct pgm_consumption
64{
65 int required; /* number tokens required before firing */
66 atomic_t token_countdown; /* consumption constraint met when <= 0 */
67};
68
69struct pgm_consume
70{
71 int nr_consumptions; /* num of consumption constraints */
72 char satisfied[FAN_BYTES]; /* bit-array of satisfied constraints;
73 bit == 0 means satisfied! */
74 struct pgm_consumption consume[0]; /* array of consumption constraints */
75};
76
77struct rt_pgm {
78 struct pgm_produce *produce; /* output and current state */
79 struct pgm_consume *consume; /* input constraints and current state */
80 struct task_struct *src; /* only not NULL if task is sink */
81};
82#endif 48#endif
83 49
84union np_flag { 50union np_flag {
@@ -118,6 +84,48 @@ struct _rt_domain;
118struct bheap_node; 84struct bheap_node;
119struct release_heap; 85struct release_heap;
120 86
87#ifdef CONFIG_PGM
88
89#define FAN_CHUNK_SIZE (sizeof(unsigned long))
90#define NR_FAN_BITS_PER_CHUNK (8*FAN_CHUNK_SIZE)
91#define NR_FAN_CHUNKS (((MAX_FAN)/(NR_FAN_BITS_PER_CHUNK)) + ((MAX_FAN)%(NR_FAN_BITS_PER_CHUNK) != 0))
92
93struct pgm_production
94{
95 struct task_struct* child; /* task that receives tokens */
96 int production_idx; /* consumption constraint index */
97 int nr_tokens; /* num tokens to generate */
98};
99
100struct pgm_produce
101{
102 unsigned long nr_productions; /* num productions/children */
103 struct pgm_production produce[0]; /* array of productions */
104};
105
106struct pgm_consumption
107{
108 unsigned long required; /* number tokens required before firing */
109 long nr_tokens; /* constraint met when >= required */
110};
111
112struct pgm_consume
113{
114 spinlock_t lock;
115 unsigned long nr_consumptions; /* num of consumption constraints */
116 unsigned long unsatisfied[NR_FAN_CHUNKS]; /* bit-array of unsatisfied constraints */
117 struct pgm_consumption consume[0]; /* array of consumption constraints */
118 //atomic_t nr_pending_release;
119};
120
121struct rt_pgm {
122 struct pgm_produce *produce; /* output and current state */
123 struct pgm_consume *consume; /* input constraints and current state */
124 struct task_struct *src; /* only not NULL if task is sink */
125};
126
127#endif /* end PGM */
128
121struct rt_job { 129struct rt_job {
122 /* Time instant the the job was or will be released. */ 130 /* Time instant the the job was or will be released. */
123 lt_t release; 131 lt_t release;
diff --git a/litmus/Makefile b/litmus/Makefile
index 4650d332fb11..40f7c97f7c0c 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -28,3 +28,5 @@ obj-$(CONFIG_FEATHER_TRACE) += ft_event.o ftdev.o
28obj-$(CONFIG_SCHED_TASK_TRACE) += sched_task_trace.o 28obj-$(CONFIG_SCHED_TASK_TRACE) += sched_task_trace.o
29obj-$(CONFIG_SCHED_DEBUG_TRACE) += sched_trace.o 29obj-$(CONFIG_SCHED_DEBUG_TRACE) += sched_trace.o
30obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o 30obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o
31
32obj-$(CONFIG_PGM) += pgm.o
diff --git a/litmus/pgm.c b/litmus/pgm.c
new file mode 100644
index 000000000000..6710644eae8e
--- /dev/null
+++ b/litmus/pgm.c
@@ -0,0 +1,131 @@
1#include <linux/sched.h>
2#include <linux/bitops.h>
3#include <linux/spinlock.h>
4
5#include <litmus/litmus.h>
6#include <litmus/sched_plugin.h>
7#include <litmus/rt_param.h>
8
9
10static inline int __is_pgm_satisfied(struct task_struct* t)
11{
12 unsigned long unsatisfied =
13 find_first_bit(tsk_rt(t)->pgm_params.consume->unsatisfied,
14 tsk_rt(t)->pgm_params.consume->nr_consumptions);
15
16 return (unsatisfied == tsk_rt(t)->pgm_params.consume->nr_consumptions);
17}
18
19int is_pgm_satisfied(struct task_struct* t)
20{
21 int is_satisfied;
22 unsigned long flags;
23
24 BUG_ON(!t);
25 BUG_ON(!is_realtime(t));
26 BUG_ON(!is_pgm(t) || is_pgm_src(t));
27
28 spin_lock_irqsave(&tsk_rt(t)->pgm_params.consume->lock, flags);
29
30 is_satisfied = __is_pgm_satisfied(t);
31
32 spin_unlock_irqrestore(&tsk_rt(t)->pgm_params.consume->lock, flags);
33
34 return (is_satisfied);
35}
36
37void pgm_produce(struct task_struct* t)
38{
39 unsigned long i;
40 struct pgm_produce *prod;
41
42 BUG_ON(!t);
43 BUG_ON(!is_realtime(t));
44 BUG_ON(!is_pgm(t) || is_pgm_sink(t));
45
46 prod = tsk_rt(t)->pgm_params.produce;
47
48 for(i = 0; i < prod->nr_productions; ++i) {
49 struct pgm_production *to_produce = &prod->produce[i];
50 struct task_struct *child = to_produce->child;
51 struct pgm_consumption *child_input;
52 int unsatisfied;
53 unsigned long flags;
54
55
56 BUG_ON(!is_pgm(child) || is_pgm_src(child));
57
58 child_input = &(tsk_rt(child)->pgm_params.consume->consume[to_produce->production_idx]);
59
60 spin_lock_irqsave(&tsk_rt(child)->pgm_params.consume->lock, flags);
61
62 child_input->nr_tokens += to_produce->nr_tokens;
63
64 if(child_input->nr_tokens >= child_input->required) {
65 unsatisfied = __test_and_clear_bit(to_produce->production_idx,
66 tsk_rt(child)->pgm_params.consume->unsatisfied);
67
68 if(unsatisfied) {
69 /* we satisfied the child's requirement */
70 if(__is_pgm_satisfied(child)) {
71 /* all requirements met: release the child */
72
73 }
74 }
75 }
76
77 spin_unlock_irqrestore(&tsk_rt(child)->pgm_params.consume->lock, flags);
78 }
79}
80
81void pgm_consume(struct task_struct* t)
82{
83 struct pgm_consume* cons;
84 unsigned long i;
85 unsigned long flags;
86
87 BUG_ON(!t);
88 BUG_ON(!is_realtime(t));
89 BUG_ON(!is_pgm(t) || is_pgm_src(t));
90
91 cons = tsk_rt(t)->pgm_params.consume;
92
93 spin_lock_irqsave(&cons->lock, flags);
94
95 for(i = 0; i < cons->nr_consumptions; ++i) {
96 cons->consume[i].nr_tokens -= cons->consume[i].required;
97 }
98
99 spin_unlock_irqrestore(&cons->lock, flags);
100}
101
102int pgm_complete(struct task_struct* t)
103{
104 struct pgm_consume* cons;
105 unsigned long i;
106 unsigned long flags;
107 int keep_going = 0;
108
109 BUG_ON(!t);
110 BUG_ON(!is_realtime(t));
111 BUG_ON(!is_pgm(t) || is_pgm_src(t));
112
113 cons = tsk_rt(t)->pgm_params.consume;
114
115 spin_lock_irqsave(&cons->lock, flags);
116
117 for(i = 0; i < cons->nr_consumptions; ++i) {
118 if(cons->consume[i].nr_tokens <= cons->consume[i].required) {
119 __set_bit(i, cons->unsatisfied);
120 }
121 }
122
123 keep_going = __is_pgm_satisfied(t);
124
125 spin_unlock_irqrestore(&cons->lock, flags);
126
127 return(keep_going);
128}
129
130
131