Round Robin Module Cleaned Up
[projects/modsched/linux.git] / framework / modules / rr_module.c
1 /*
2  * rr_module.c
3  *      a simple round robin scheduler
4  *
5  *  Created on: 14.06.2013
6  *      Author: Rene Sechting
7  */
8
9 #include <fw.h>
10 #include <fw_comm.h>
11
12 struct rq{
13         fw_list_head_t          queue;
14         struct fw_task          *curr;
15         struct fw_task          *idle;
16 };
17
18 struct rr_info{
19         struct fw_list_head head;
20         struct fw_task *task;
21         int on_rq;
22 };
23
24 static struct rq *rr_rq;
25 static struct fw_task *idle;
26
27 static int module_id;
28
29 static struct fw_task *task_received(struct fw_task *task)
30 {
31         struct rr_info *rq_ele;
32
33         rq_ele = (struct rr_info *)fw_malloc(sizeof(struct rr_info));
34         task->module_data[module_id] = (void *)rq_ele;
35         rq_ele->task = task;
36         fw_list_add_tail(&rq_ele->head, &rr_rq->queue);
37
38         rq_ele->on_rq = 1;
39
40         return NULL;
41 }
42
43 static struct fw_task *task_finished(struct fw_task *finished)
44 {
45         struct rr_info *next_elem;
46         struct fw_task *task;
47
48         if(!fw_list_empty(&rr_rq->queue)){
49                 //get the next task running!
50                 next_elem = (struct rr_info *)__fw_list_pop(&(rr_rq->queue));
51                 task = next_elem->task;
52                 rr_rq->curr = task;
53                 fw_dispatch(task);
54                 return task;
55         }else{
56                 //every task is done, go to idle mode
57                 rr_rq->curr = idle;
58                 fw_dispatch(idle);
59                 return idle;
60         }
61 }
62
63 static struct fw_task *tick_received(struct fw_task *preempted)
64 {
65         struct fw_task *task;
66         struct rr_info *next_elem;
67
68         if(fw_list_empty(&rr_rq->queue)){
69                 fw_dispatch(preempted);
70                 return NULL;
71         }
72
73         if((preempted == idle)){
74                 next_elem = (struct rr_info *)__fw_list_pop(&(rr_rq->queue));
75                 task = next_elem->task;
76                 rr_rq->curr = task;
77                 fw_dispatch(task);
78                 return task;
79         }else{
80                 //insert curr task to queue
81                 next_elem = (struct rr_info*)preempted->module_data[module_id];
82                 fw_list_add_tail(&next_elem->head,&rr_rq->queue);
83                 next_elem->on_rq = 1;
84                 next_elem = (struct rr_info *)__fw_list_pop(&(rr_rq->queue));
85                 task = next_elem->task;
86                 next_elem->on_rq = 0;
87                 rr_rq->curr = task;
88                 fw_dispatch(task);
89                 return task;
90         }
91         rr_rq->curr = idle;
92         fw_dispatch(idle);
93         return idle;
94 }
95
96 static struct fw_task *task_yielded(struct fw_task *yielded)
97 {
98
99         struct rr_info *next_elem;
100         struct fw_task *task;
101         next_elem = (struct rr_info*)yielded->module_data[module_id];
102         next_elem->on_rq = 0;
103         if(!fw_list_empty(&rr_rq->queue)){
104                 next_elem = (struct rr_info *)__fw_list_pop(&(rr_rq->queue));
105                 next_elem->on_rq = 0;
106                 task = next_elem->task;
107                 rr_rq->curr = task;
108                 fw_dispatch(task);
109                 return task;
110         }else{
111                 rr_rq->curr = idle;
112                 fw_dispatch(idle);
113                 return idle;
114         }
115 }
116
117 static struct fw_task *wake_up_task(struct fw_task *wake_up)
118 {
119         struct rr_info *to_wake_up = (struct rr_info*)wake_up->module_data[module_id];
120         if(!to_wake_up->on_rq){
121                 fw_list_add_tail(&to_wake_up->head,&(rr_rq->queue));
122                 to_wake_up->on_rq = 1;
123         }
124         return NULL;
125 }
126
127 int init_sched_rr_module(void)
128 {
129         fw_printf("ROUND_ROBIN_MODULE INITIALIZING\n");
130         module_id = fw_register_module();
131         if(module_id == -1)
132                 return -1;
133         rr_rq = (struct rq*)fw_malloc(sizeof(struct rq));
134         idle = fw_idle_task;
135         rr_rq->idle = idle;
136         rr_rq->curr = idle;
137         FW_LIST_INIT(rr_rq->queue);
138         fw_subscribe(ADMIT, &task_received);
139         fw_subscribe(RELEASE, &task_finished);
140         fw_subscribe(TIME_OUT, &tick_received);
141         fw_subscribe(EVENT_WAIT, &task_yielded);
142         fw_subscribe(EVENT_OCCURS, &wake_up_task);
143         return 0;
144 }