diff options
-rw-r--r-- | include/litmus/servers.h | 179 | ||||
-rw-r--r-- | litmus/sched_edf_hsb.c | 53 | ||||
-rw-r--r-- | litmus/servers.c | 275 |
3 files changed, 279 insertions, 228 deletions
diff --git a/include/litmus/servers.h b/include/litmus/servers.h index 97fd0ce76207..d3e45857653b 100644 --- a/include/litmus/servers.h +++ b/include/litmus/servers.h | |||
@@ -3,125 +3,161 @@ | |||
3 | 3 | ||
4 | struct server; | 4 | struct server; |
5 | struct periodic_server; | 5 | struct periodic_server; |
6 | struct proc_read_args; | ||
7 | struct proc_dir_entry; | 6 | struct proc_dir_entry; |
8 | struct server_domain; | 7 | struct server_domain; |
9 | struct server_release_heap; | 8 | struct server_release_heap; |
9 | struct completion_timer; | ||
10 | struct server_proc; | ||
10 | 11 | ||
11 | #define SERVER_RELEASE_QUEUE_SLOTS 127 | 12 | #define SERVER_RELEASE_QUEUE_SLOTS 127 |
12 | 13 | ||
13 | #define SERVER_FMT "{server/%d:%d}" | 14 | #define SERVER_FMT "{server/%d:%d}" |
14 | #define SERVER_ARGS(s) (s)->id, (s)->job_no | 15 | #define SERVER_ARGS(s) (s)->id, (s)->job_no |
15 | 16 | ||
17 | #define server_task(s) (((s)->cpu != NO_CPU)?s->domain->linked_tasks[(s)->cpu]:NULL) | ||
18 | #define is_server_linked(s) ((s)->cpu != NO_CPU) | ||
19 | |||
16 | /* | 20 | /* |
17 | * Called when a server is released. | 21 | * A single schedulable server. |
18 | */ | ||
19 | typedef void (*post_release_t)(struct periodic_server *server); | ||
20 | /* | ||
21 | * Called when a server exhausts its budget. | ||
22 | */ | ||
23 | typedef void (*server_completed_t)(struct server *server, | ||
24 | struct task_struct *was_running); | ||
25 | /* | ||
26 | * Used to read server entries. | ||
27 | */ | ||
28 | typedef int (*admit_server_t)(unsigned long long wcet, | ||
29 | unsigned long long period, int cpu); | ||
30 | /* | ||
31 | * Must call server_proc_read on each server to print. | ||
32 | */ | ||
33 | typedef void (*list_servers_t)(struct proc_read_args *args); | ||
34 | /* | ||
35 | * Called after each proc write before new values are read. | ||
36 | */ | ||
37 | typedef void (*stop_servers_t)(void); | ||
38 | /* | ||
39 | * Called when a group of servers release | ||
40 | */ | 22 | */ |
41 | typedef void (*servers_released_t)(struct list_head *servers); | ||
42 | |||
43 | typedef struct server { | 23 | typedef struct server { |
44 | /* Specified by the user */ | 24 | /* Specified by the user */ |
45 | int id; | 25 | int id; |
46 | lt_t wcet; | 26 | lt_t wcet; |
47 | lt_t period; | 27 | lt_t period; |
48 | 28 | ||
29 | /* Optional */ | ||
30 | int type; | ||
31 | void* data; | ||
32 | |||
49 | /* Managed internally */ | 33 | /* Managed internally */ |
50 | lt_t deadline; | 34 | lt_t deadline; |
51 | lt_t release; | 35 | lt_t release; |
52 | lt_t budget; /* The remaining budget for current period */ | 36 | lt_t budget; /* The remaining budget for current period */ |
53 | lt_t start_time; /* The time the server started executing or 0 */ | ||
54 | int running; /* True if server is currently executing */ | ||
55 | int job_no; /* Current job of server */ | 37 | int job_no; /* Current job of server */ |
38 | int cpu; /* CPU the server is running on or NO_CPU */ | ||
56 | 39 | ||
57 | int type; /* Optional */ | 40 | struct server_domain *domain; |
58 | |||
59 | /* Used for grouped releases */ | ||
60 | struct server_release_heap *release_heap; | ||
61 | struct list_head release_list; | ||
62 | 41 | ||
63 | /* Useful in general */ | 42 | /* For membership in collections */ |
64 | struct bheap_node *hn; | 43 | struct bheap_node *hn; |
65 | struct list_head list; | 44 | struct list_head list; |
66 | 45 | ||
67 | void* data; | 46 | /* Used for grouped releases */ |
68 | 47 | struct server_release_heap *release_heap; | |
69 | struct task_struct* scheduled; | 48 | struct list_head release_list; |
70 | } server_t; | 49 | } server_t; |
71 | 50 | ||
72 | /* | 51 | /* |
73 | * Because pointer arithmetic wasn't working. TODO: pointer arithmetic | 52 | * Called when a server exhausts its budget. |
74 | */ | 53 | */ |
75 | typedef struct completion_timer { | 54 | typedef void (*server_completed_t)(struct server *server, |
76 | int armed; | 55 | struct task_struct *was_running); |
77 | int cpu; | 56 | /* |
78 | struct hrtimer timer; | 57 | * Called when a group of servers release |
79 | struct hrtimer_start_on_info info; | 58 | */ |
80 | struct server_domain *domain; | 59 | typedef void (*servers_released_t)(struct list_head *servers); |
81 | } completion_timer_t; | 60 | /* |
61 | * Used to read server entries. | ||
62 | */ | ||
63 | typedef int (*admit_server_t)(unsigned long long wcet, | ||
64 | unsigned long long period, int cpu); | ||
65 | /* | ||
66 | * Lists all servers for a proc entry by calling list_server on each. | ||
67 | */ | ||
68 | typedef void (*list_servers_t)(struct server_proc *proc); | ||
69 | /* | ||
70 | * Stop all servers. Used to destroy servers on a proc entry rewrite. | ||
71 | */ | ||
72 | typedef void (*stop_servers_t)(void); | ||
82 | 73 | ||
83 | /* | 74 | /* |
84 | * Useful tools for scheduling servers. | 75 | * Useful tools for scheduling servers. |
85 | */ | 76 | */ |
86 | typedef struct server_domain { | 77 | typedef struct server_domain { |
78 | /* Collection of grouped releases */ | ||
87 | raw_spinlock_t release_lock; | 79 | raw_spinlock_t release_lock; |
88 | struct list_head release_queue[SERVER_RELEASE_QUEUE_SLOTS]; | 80 | struct list_head release_queue[SERVER_RELEASE_QUEUE_SLOTS]; |
89 | 81 | ||
90 | int release_master; | 82 | /* List of tasks to be added to the grouped releases */ |
83 | raw_spinlock_t tobe_lock; | ||
84 | struct list_head tobe_released; | ||
91 | 85 | ||
92 | completion_timer_t* completion_timers; | 86 | /* CPU on which to release servers */ |
93 | server_t** running; | 87 | int release_master; |
94 | 88 | ||
95 | raw_spinlock_t* timer_lock; | 89 | /* Per CPU information for running servers */ |
90 | struct completion_timer* completion_timers; | ||
91 | server_t** linked_servers; | ||
92 | struct task_struct** linked_tasks; | ||
93 | lt_t* start_times; | ||
96 | 94 | ||
95 | /* Used to lock firing of the completion timer. | ||
96 | * This is needed here and not for the release timer because | ||
97 | * the completion timer actually modifies the state of the | ||
98 | * server itself. | ||
99 | */ | ||
100 | raw_spinlock_t* completion_lock; | ||
101 | |||
102 | /* Event callbacks */ | ||
97 | server_completed_t server_completed; | 103 | server_completed_t server_completed; |
98 | servers_released_t servers_released; | 104 | servers_released_t servers_released; |
99 | 105 | ||
100 | struct kmem_cache *server_release_cache; | 106 | /* Proc entries for controlling groups of servers */ |
101 | 107 | struct list_head server_procs; | |
102 | raw_spinlock_t tobe_lock; | ||
103 | struct list_head tobe_released; | ||
104 | } server_domain_t; | 108 | } server_domain_t; |
105 | 109 | ||
106 | /* | 110 | /* |
107 | * A group of servers releasing simultaneously. | 111 | * A group of servers releasing simultaneously. |
108 | */ | 112 | */ |
109 | typedef struct server_release_heap { | 113 | typedef struct server_release_heap { |
110 | struct list_head list; | 114 | /* Servers to be released */ |
111 | lt_t release_time; | 115 | struct list_head servers; |
116 | lt_t release_time; | ||
112 | 117 | ||
113 | struct list_head servers; | 118 | /* For membership in the domain */ |
119 | struct list_head list; | ||
120 | |||
121 | /* For callbacks */ | ||
122 | server_domain_t *domain; | ||
114 | 123 | ||
115 | struct hrtimer timer; | 124 | struct hrtimer timer; |
116 | struct hrtimer_start_on_info info; | 125 | struct hrtimer_start_on_info info; |
117 | |||
118 | server_domain_t *domain; | ||
119 | } server_release_heap_t; | 126 | } server_release_heap_t; |
120 | 127 | ||
121 | /* | 128 | /* |
129 | * A timer for managing server completions. Can be managed concurrently. | ||
130 | */ | ||
131 | typedef struct completion_timer { | ||
132 | int armed; /* Is the timer armed or not? Seperate from the timer | ||
133 | * so that it can be used to disarm a timer which | ||
134 | * is already firing. | ||
135 | */ | ||
136 | int cpu; /* CPU where the server is running. This is not the | ||
137 | * cpu on which the timer will fire. | ||
138 | */ | ||
139 | struct hrtimer timer; | ||
140 | struct hrtimer_start_on_info info; | ||
141 | struct server_domain *domain; /* For callbacks */ | ||
142 | } completion_timer_t; | ||
143 | |||
144 | /* | ||
145 | * A proc directory entry which controls a group of servers. | ||
146 | */ | ||
147 | typedef struct server_proc { | ||
148 | struct proc_dir_entry *entry; | ||
149 | struct list_head list; | ||
150 | admit_server_t admit_server; /* Add a server from the entry */ | ||
151 | list_servers_t list_servers; /* List each server in the entry */ | ||
152 | stop_servers_t stop_servers; /* Disables all servers in the entry */ | ||
153 | char* page; /* Used internally by proc */ | ||
154 | int length; /* Used internally by proc */ | ||
155 | } server_proc_t; | ||
156 | |||
157 | /* | ||
122 | * Initialize and exit servers | 158 | * Initialize and exit servers |
123 | */ | 159 | */ |
124 | void server_init(server_t *server, int id, | 160 | void server_init(server_t *server, server_domain_t *domain, int id, |
125 | lt_t wcet, lt_t period, int grouped); | 161 | lt_t wcet, lt_t period, int grouped); |
126 | void server_destroy(server_t *server); | 162 | void server_destroy(server_t *server); |
127 | 163 | ||
@@ -137,7 +173,7 @@ void server_free(server_t *server); | |||
137 | void server_domain_init(server_domain_t *domain, | 173 | void server_domain_init(server_domain_t *domain, |
138 | servers_released_t servers_released, | 174 | servers_released_t servers_released, |
139 | server_completed_t server_completed, | 175 | server_completed_t server_completed, |
140 | int release_master, raw_spinlock_t* timer_lock); | 176 | int release_master, raw_spinlock_t* completion_lock); |
141 | void server_domain_destroy(server_domain_t *domain); | 177 | void server_domain_destroy(server_domain_t *domain); |
142 | 178 | ||
143 | /* | 179 | /* |
@@ -148,13 +184,12 @@ int add_server_release(server_t *server, server_domain_t *server_domain); | |||
148 | /* | 184 | /* |
149 | * Runs a task on the server. | 185 | * Runs a task on the server. |
150 | */ | 186 | */ |
151 | void server_run(server_t *server, struct task_struct *task, | 187 | void server_run(server_t *server, struct task_struct *task); |
152 | server_domain_t *server_domain); | ||
153 | 188 | ||
154 | /* | 189 | /* |
155 | * Stops server execution. | 190 | * Stops server execution. |
156 | */ | 191 | */ |
157 | void server_stop(server_t *server, server_domain_t *domain); | 192 | void server_stop(server_t *server); |
158 | 193 | ||
159 | /* | 194 | /* |
160 | * Begins a server's next period. | 195 | * Begins a server's next period. |
@@ -167,20 +202,18 @@ void server_release(server_t *server); | |||
167 | void server_release_at(server_t *server, lt_t time); | 202 | void server_release_at(server_t *server, lt_t time); |
168 | 203 | ||
169 | /* | 204 | /* |
170 | * Call once for every server which should be printed | 205 | * Call once for every server which should be printed by list_servers. |
171 | * out on a proc dir read. Should be called inside a list_servers_t | ||
172 | * method. | ||
173 | */ | 206 | */ |
174 | void server_proc_read_single(server_t *server, int cpu, | 207 | void list_server(server_t *server, int cpu, server_proc_t *proc); |
175 | struct proc_read_args *args); | ||
176 | 208 | ||
177 | /* | 209 | /* |
178 | * Create and destroy a proc dir entry with the given file name. | 210 | * Create and destroy a proc dir entry with the given file name. |
179 | */ | 211 | */ |
180 | int server_proc_init(struct proc_dir_entry *proc_dir, char *file, | 212 | server_proc_t* server_proc_init(server_domain_t *domain, |
181 | admit_server_t admit_server, | 213 | struct proc_dir_entry *proc_dir, char *file, |
182 | list_servers_t list_servers, | 214 | admit_server_t admit_server, |
183 | stop_servers_t stop_servers); | 215 | list_servers_t list_servers, |
184 | void server_proc_exit(struct proc_dir_entry *proc_dir, char *file); | 216 | stop_servers_t stop_servers); |
217 | void server_proc_exit(server_proc_t *proc); | ||
185 | 218 | ||
186 | #endif | 219 | #endif |
diff --git a/litmus/sched_edf_hsb.c b/litmus/sched_edf_hsb.c index e3cd78d29ce8..26f32d874916 100644 --- a/litmus/sched_edf_hsb.c +++ b/litmus/sched_edf_hsb.c | |||
@@ -293,7 +293,7 @@ static void donate_slack(server_t *donator, struct task_struct *was_scheduled) | |||
293 | TRACE_SERVER_SUB(donator, "donated %llu slack", TIME(donator->budget)); | 293 | TRACE_SERVER_SUB(donator, "donated %llu slack", TIME(donator->budget)); |
294 | sched_trace_action(was_scheduled, 9); | 294 | sched_trace_action(was_scheduled, 9); |
295 | slack = server_alloc(GFP_ATOMIC); | 295 | slack = server_alloc(GFP_ATOMIC); |
296 | server_init(slack, donator->id, donator->budget, | 296 | server_init(slack, &server_domain, donator->id, donator->budget, |
297 | donator->period, 0); | 297 | donator->period, 0); |
298 | slack->type = S_SLACK; | 298 | slack->type = S_SLACK; |
299 | server_release_at(slack, donator->release); | 299 | server_release_at(slack, donator->release); |
@@ -606,7 +606,7 @@ static noinline void link_server(cpu_entry_t *entry, | |||
606 | } | 606 | } |
607 | 607 | ||
608 | entry->linked_server = next_server; | 608 | entry->linked_server = next_server; |
609 | server_run(entry->linked_server, entry->linked, &server_domain); | 609 | server_run(entry->linked_server, entry->linked); |
610 | } | 610 | } |
611 | 611 | ||
612 | /* | 612 | /* |
@@ -624,7 +624,7 @@ static noinline void unlink_server(cpu_entry_t *entry, | |||
624 | if (!entry->linked_server) | 624 | if (!entry->linked_server) |
625 | return; | 625 | return; |
626 | 626 | ||
627 | server_stop(entry->linked_server, &server_domain); | 627 | server_stop(entry->linked_server); |
628 | now = litmus_clock(); | 628 | now = litmus_clock(); |
629 | 629 | ||
630 | if (is_hrt(entry->linked) && !hrt_server->ready) { | 630 | if (is_hrt(entry->linked) && !hrt_server->ready) { |
@@ -837,8 +837,6 @@ static inline void catchup_server(server_t *server, lt_t time) | |||
837 | lt_t diff = time - server->deadline; | 837 | lt_t diff = time - server->deadline; |
838 | lt_t sub = diff % server->period; | 838 | lt_t sub = diff % server->period; |
839 | 839 | ||
840 | BUG_ON(server->running); | ||
841 | |||
842 | server_release_at(server, time - sub); | 840 | server_release_at(server, time - sub); |
843 | TRACE_SUB("catching up server %d to %llu", | 841 | TRACE_SUB("catching up server %d to %llu", |
844 | server->id, server->deadline); | 842 | server->id, server->deadline); |
@@ -856,8 +854,9 @@ static struct task_struct* next_eligible_hrt(hrt_server_t *hrt_server) | |||
856 | lt_t now = litmus_clock(); | 854 | lt_t now = litmus_clock(); |
857 | struct task_struct *task = NULL; | 855 | struct task_struct *task = NULL; |
858 | 856 | ||
859 | /* Catch up server if it is late */ | 857 | /* Catch up server if it is initialized, not running, and late */ |
860 | if (hrt_server->server.deadline && !hrt_server->server.running && | 858 | if (hrt_server->server.deadline && |
859 | !is_server_linked(&hrt_server->server) && | ||
861 | lt_before_eq(hrt_server->server.deadline, now)) { | 860 | lt_before_eq(hrt_server->server.deadline, now)) { |
862 | catchup_server(&hrt_server->server, now); | 861 | catchup_server(&hrt_server->server, now); |
863 | slack_timer_arm(hrt_server); | 862 | slack_timer_arm(hrt_server); |
@@ -1659,7 +1658,8 @@ static int admit_be_server(unsigned long long wcet, | |||
1659 | } | 1658 | } |
1660 | 1659 | ||
1661 | be_server = server_alloc(GFP_ATOMIC); | 1660 | be_server = server_alloc(GFP_ATOMIC); |
1662 | server_init(be_server, BE_SERVER_BASE + ++curr_be, | 1661 | server_init(be_server, &server_domain, |
1662 | BE_SERVER_BASE + ++curr_be, | ||
1663 | wcet, period, 1); | 1663 | wcet, period, 1); |
1664 | be_server->type = S_BE; | 1664 | be_server->type = S_BE; |
1665 | 1665 | ||
@@ -1674,14 +1674,14 @@ static int admit_be_server(unsigned long long wcet, | |||
1674 | /* | 1674 | /* |
1675 | * Output all BE servers to a proc entry. | 1675 | * Output all BE servers to a proc entry. |
1676 | */ | 1676 | */ |
1677 | static void list_be_servers(struct proc_read_args *args) | 1677 | static void list_be_servers(server_proc_t *proc) |
1678 | { | 1678 | { |
1679 | struct list_head *pos; | 1679 | struct list_head *pos; |
1680 | server_t *be_server; | 1680 | server_t *be_server; |
1681 | 1681 | ||
1682 | list_for_each(pos, &be_servers) { | 1682 | list_for_each(pos, &be_servers) { |
1683 | be_server = list_entry(pos, server_t, list); | 1683 | be_server = list_entry(pos, server_t, list); |
1684 | server_proc_read_single(be_server, NO_CPU, args); | 1684 | list_server(be_server, NO_CPU, proc); |
1685 | } | 1685 | } |
1686 | } | 1686 | } |
1687 | 1687 | ||
@@ -1724,7 +1724,8 @@ static int admit_hrt_server(unsigned long long wcet, | |||
1724 | 1724 | ||
1725 | hrt_server->no_slack = 0; | 1725 | hrt_server->no_slack = 0; |
1726 | 1726 | ||
1727 | server_init(&hrt_server->server, cpu, wcet, period, 1); | 1727 | server_init(&hrt_server->server, &server_domain, |
1728 | cpu, wcet, period, 1); | ||
1728 | hrt_server->server.type = S_HRT; | 1729 | hrt_server->server.type = S_HRT; |
1729 | 1730 | ||
1730 | edf_domain_init(&hrt_server->hrt_domain, NULL, | 1731 | edf_domain_init(&hrt_server->hrt_domain, NULL, |
@@ -1741,16 +1742,16 @@ static int admit_hrt_server(unsigned long long wcet, | |||
1741 | /* | 1742 | /* |
1742 | * Print all HRT servers to a proc entry. | 1743 | * Print all HRT servers to a proc entry. |
1743 | */ | 1744 | */ |
1744 | static void list_hrt_servers(struct proc_read_args *args) | 1745 | static void list_hrt_servers(server_proc_t *proc) |
1745 | { | 1746 | { |
1746 | cpu_entry_t *entry; | 1747 | cpu_entry_t *entry; |
1747 | hrt_server_t *hrt_server; | 1748 | hrt_server_t *hrt_server; |
1748 | int cpu; | 1749 | int cpu; |
1749 | 1750 | ||
1750 | for_each_online_cpu(cpu) { | 1751 | for_each_online_cpu(cpu) { |
1751 | entry = &per_cpu(cpu_entries, cpu); | 1752 | entry = &per_cpu(cpu_entries, cpu); |
1752 | hrt_server = &entry->hrt_server; | 1753 | hrt_server = &entry->hrt_server; |
1753 | server_proc_read_single(&hrt_server->server, cpu, args); | 1754 | list_server(&hrt_server->server, cpu, proc); |
1754 | } | 1755 | } |
1755 | } | 1756 | } |
1756 | 1757 | ||
@@ -2048,7 +2049,8 @@ static void edf_hsb_task_new(struct task_struct *task, int on_rq, int running) | |||
2048 | if (is_srt(task)) { | 2049 | if (is_srt(task)) { |
2049 | /* Create SRT server */ | 2050 | /* Create SRT server */ |
2050 | srt_server = server_alloc(GFP_ATOMIC); | 2051 | srt_server = server_alloc(GFP_ATOMIC); |
2051 | server_init(srt_server, task->pid, get_exec_cost(task), | 2052 | server_init(srt_server, &server_domain, |
2053 | task->pid, get_exec_cost(task), | ||
2052 | get_rt_period(task), 0); | 2054 | get_rt_period(task), 0); |
2053 | srt_server->type = S_SRT; | 2055 | srt_server->type = S_SRT; |
2054 | srt_server->data = task; | 2056 | srt_server->data = task; |
@@ -2157,13 +2159,6 @@ static int __init init_edf_hsb(void) | |||
2157 | goto out; | 2159 | goto out; |
2158 | } | 2160 | } |
2159 | 2161 | ||
2160 | /* Server proc interfaces */ | ||
2161 | rv = server_proc_init(edf_hsb_proc_dir, BE_PROC_NAME, | ||
2162 | admit_be_server, list_be_servers, | ||
2163 | stop_be_servers); | ||
2164 | rv = server_proc_init(edf_hsb_proc_dir, HRT_PROC_NAME, | ||
2165 | admit_hrt_server, list_hrt_servers, | ||
2166 | stop_hrt_servers); | ||
2167 | 2162 | ||
2168 | task_data_cache = KMEM_CACHE(task_data, SLAB_PANIC); | 2163 | task_data_cache = KMEM_CACHE(task_data, SLAB_PANIC); |
2169 | 2164 | ||
@@ -2174,6 +2169,17 @@ static int __init init_edf_hsb(void) | |||
2174 | server_domain_init(&server_domain, servers_released, | 2169 | server_domain_init(&server_domain, servers_released, |
2175 | server_completed, NO_CPU, global_lock); | 2170 | server_completed, NO_CPU, global_lock); |
2176 | 2171 | ||
2172 | /* Server proc interfaces */ | ||
2173 | server_proc_init(&server_domain, | ||
2174 | edf_hsb_proc_dir, BE_PROC_NAME, | ||
2175 | admit_be_server, list_be_servers, | ||
2176 | stop_be_servers); | ||
2177 | server_proc_init(&server_domain, | ||
2178 | edf_hsb_proc_dir, HRT_PROC_NAME, | ||
2179 | admit_hrt_server, list_hrt_servers, | ||
2180 | stop_hrt_servers); | ||
2181 | |||
2182 | |||
2177 | /* Global collections */ | 2183 | /* Global collections */ |
2178 | bheap_init(&cpu_heap); | 2184 | bheap_init(&cpu_heap); |
2179 | bheap_init(&be_ready_servers); | 2185 | bheap_init(&be_ready_servers); |
@@ -2216,9 +2222,6 @@ static void exit_edf_hsb(void) | |||
2216 | stop_be_servers(); | 2222 | stop_be_servers(); |
2217 | stop_hrt_servers(); | 2223 | stop_hrt_servers(); |
2218 | 2224 | ||
2219 | server_proc_exit(edf_hsb_proc_dir, BE_PROC_NAME); | ||
2220 | server_proc_exit(edf_hsb_proc_dir, HRT_PROC_NAME); | ||
2221 | |||
2222 | server_domain_destroy(&server_domain); | 2225 | server_domain_destroy(&server_domain); |
2223 | 2226 | ||
2224 | for_each_online_cpu(cpu) { | 2227 | for_each_online_cpu(cpu) { |
diff --git a/litmus/servers.c b/litmus/servers.c index 4011bc3c144b..6ee70d928051 100644 --- a/litmus/servers.c +++ b/litmus/servers.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * TODO: memory leaks for stopping | 2 | * TODO: change from destroy to exit, rename server proc stuff |
3 | */ | 3 | */ |
4 | #include <linux/hrtimer.h> | 4 | #include <linux/hrtimer.h> |
5 | #include <linux/percpu.h> | 5 | #include <linux/percpu.h> |
@@ -22,18 +22,17 @@ | |||
22 | ({lt_t y = x; \ | 22 | ({lt_t y = x; \ |
23 | do_div(y, NSEC_PER_MSEC); \ | 23 | do_div(y, NSEC_PER_MSEC); \ |
24 | y;}) | 24 | y;}) |
25 | |||
26 | #ifdef DEBUG_SERVERS | 25 | #ifdef DEBUG_SERVERS |
27 | #define _TRACE_SUB(fmt, args...) \ | 26 | #define _TRACE_SUB(fmt, args...) \ |
28 | sched_trace_log_message("%d P%d -[%s@%s:%d]: " fmt "\n", \ | 27 | sched_trace_log_message("%d P%d -[%s@%s:%d]: " fmt "\n", \ |
29 | TRACE_ARGS, ## args) | 28 | TRACE_ARGS, ## args) |
30 | #define TRACE_SUB(s, fmt, args...) \ | 29 | #define TRACE_SUB(s, fmt, args...) \ |
31 | do {\ | 30 | do {\ |
32 | if ((s)->running) \ | 31 | if (is_server_linked(s)) \ |
33 | _TRACE_SUB("(%s/%d:%d) " SERVER_FMT " " fmt, \ | 32 | _TRACE_SUB("(%s/%d:%d) " SERVER_FMT " " fmt, \ |
34 | (s)->scheduled->comm, \ | 33 | server_task(s)->comm, \ |
35 | (s)->scheduled->pid, \ | 34 | server_task(s)->pid, \ |
36 | (s)->scheduled->rt_param.job_params.job_no, \ | 35 | server_task(s)->rt_param.job_params.job_no, \ |
37 | SERVER_ARGS(s), ##args); \ | 36 | SERVER_ARGS(s), ##args); \ |
38 | else \ | 37 | else \ |
39 | _TRACE_SUB("(NULL) " SERVER_FMT " " fmt, \ | 38 | _TRACE_SUB("(NULL) " SERVER_FMT " " fmt, \ |
@@ -45,11 +44,11 @@ | |||
45 | TRACE_ARGS, ## args, TIME(litmus_clock())) | 44 | TRACE_ARGS, ## args, TIME(litmus_clock())) |
46 | #define TRACE_TIMER(s, fmt, args...) \ | 45 | #define TRACE_TIMER(s, fmt, args...) \ |
47 | do { \ | 46 | do { \ |
48 | if ((s)->running) \ | 47 | if (is_server_linked(s)) \ |
49 | _TRACE_TIMER("(%s/%d:%d) " SERVER_FMT " " fmt, \ | 48 | _TRACE_TIMER("(%s/%d:%d) " SERVER_FMT " " fmt, \ |
50 | (s)->scheduled->comm, \ | 49 | server_task(s)->comm, \ |
51 | (s)->scheduled->pid, \ | 50 | server_task(s)->pid, \ |
52 | (s)->scheduled->rt_param.job_params.job_no, \ | 51 | server_task(s)->rt_param.job_params.job_no, \ |
53 | SERVER_ARGS(s), ##args); \ | 52 | SERVER_ARGS(s), ##args); \ |
54 | else \ | 53 | else \ |
55 | _TRACE_TIMER("(NULL) " SERVER_FMT " " fmt, \ | 54 | _TRACE_TIMER("(NULL) " SERVER_FMT " " fmt, \ |
@@ -69,17 +68,6 @@ DEFINE_PER_CPU(struct hrtimer_start_on_info, server_cpu_infos); | |||
69 | struct kmem_cache *server_release_cache; | 68 | struct kmem_cache *server_release_cache; |
70 | struct kmem_cache *server_cache; | 69 | struct kmem_cache *server_cache; |
71 | 70 | ||
72 | typedef struct proc_read_args { | ||
73 | char *page; | ||
74 | int length; | ||
75 | } proc_read_args_t; | ||
76 | |||
77 | typedef struct { | ||
78 | admit_server_t admit_server; | ||
79 | list_servers_t list_servers; | ||
80 | stop_servers_t stop_servers; | ||
81 | } methods_t; | ||
82 | |||
83 | /* | 71 | /* |
84 | * Okay to call if the timer is not armed. | 72 | * Okay to call if the timer is not armed. |
85 | */ | 73 | */ |
@@ -94,8 +82,8 @@ static inline int timer_cancel(struct hrtimer *timer) | |||
94 | static int completion_timer_arm(server_domain_t* domain, int cpu) | 82 | static int completion_timer_arm(server_domain_t* domain, int cpu) |
95 | { | 83 | { |
96 | int err = 0, on_cpu; | 84 | int err = 0, on_cpu; |
97 | lt_t now = litmus_clock(); | 85 | lt_t now = domain->start_times[cpu]; |
98 | server_t *server = domain->running[cpu]; | 86 | server_t *server = domain->linked_servers[cpu]; |
99 | lt_t budget_exhausted = now + server->budget; | 87 | lt_t budget_exhausted = now + server->budget; |
100 | 88 | ||
101 | /* This happens when someone attempts to call server_run when | 89 | /* This happens when someone attempts to call server_run when |
@@ -113,7 +101,7 @@ static int completion_timer_arm(server_domain_t* domain, int cpu) | |||
113 | return 0; | 101 | return 0; |
114 | } | 102 | } |
115 | 103 | ||
116 | TRACE_SUB(server, "start time: %llu", server->start_time); | 104 | TRACE_SUB(server, "start time: %llu", domain->start_times[cpu]); |
117 | 105 | ||
118 | #ifdef COMPLETION_ON_MASTER | 106 | #ifdef COMPLETION_ON_MASTER |
119 | if (domain->release_master != NO_CPU) | 107 | if (domain->release_master != NO_CPU) |
@@ -151,26 +139,6 @@ static int completion_timer_arm(server_domain_t* domain, int cpu) | |||
151 | return 1; | 139 | return 1; |
152 | } | 140 | } |
153 | 141 | ||
154 | void server_run(server_t *server, struct task_struct *task, | ||
155 | server_domain_t *domain) | ||
156 | { | ||
157 | int cpu = task->rt_param.linked_on; | ||
158 | |||
159 | BUG_ON(server->scheduled); | ||
160 | BUG_ON(server->running); | ||
161 | BUG_ON(cpu == NO_CPU); | ||
162 | BUG_ON(domain->running[cpu]); | ||
163 | |||
164 | server->scheduled = task; | ||
165 | server->running = 1; | ||
166 | server->start_time = litmus_clock(); | ||
167 | |||
168 | domain->running[cpu] = server; | ||
169 | domain->completion_timers[cpu].armed =completion_timer_arm(domain, cpu); | ||
170 | |||
171 | TRACE_SUB(server, "running on cpu P%d", task->rt_param.linked_on); | ||
172 | } | ||
173 | |||
174 | static enum hrtimer_restart completion_timer_fire(struct hrtimer *timer) | 142 | static enum hrtimer_restart completion_timer_fire(struct hrtimer *timer) |
175 | { | 143 | { |
176 | int cpu; | 144 | int cpu; |
@@ -188,22 +156,22 @@ static enum hrtimer_restart completion_timer_fire(struct hrtimer *timer) | |||
188 | domain = completion_timer->domain; | 156 | domain = completion_timer->domain; |
189 | cpu = completion_timer->cpu; | 157 | cpu = completion_timer->cpu; |
190 | 158 | ||
191 | raw_spin_lock_irqsave(domain->timer_lock, flags); | 159 | raw_spin_lock_irqsave(domain->completion_lock, flags); |
192 | 160 | ||
193 | _TRACE_TIMER("completion timer firing on P%d"); | 161 | _TRACE_TIMER("completion timer firing on P%d"); |
194 | 162 | ||
195 | /* We got the lock before someone tried to re-arm. Proceed. */ | 163 | /* We got the lock before someone tried to re-arm. Proceed. */ |
196 | if (completion_timer->armed) { | 164 | if (completion_timer->armed) { |
197 | server = domain->running[cpu]; | 165 | server = domain->linked_servers[cpu]; |
198 | TRACE_SUB(server, "completed"); | 166 | TRACE_SUB(server, "completed"); |
199 | 167 | ||
200 | was_running = server->scheduled; | 168 | was_running = server_task(server); |
201 | 169 | ||
202 | server->budget = 0; | 170 | server->budget = 0; |
203 | server->running = 0; | 171 | server->cpu = NO_CPU; |
204 | server->scheduled = NULL; | 172 | domain->start_times[cpu] = 0; |
205 | server->start_time = 0; | 173 | domain->linked_servers[cpu] = NULL; |
206 | domain->running[cpu] = NULL; | 174 | domain->linked_tasks[cpu] = NULL; |
207 | 175 | ||
208 | domain->server_completed(server, was_running); | 176 | domain->server_completed(server, was_running); |
209 | } | 177 | } |
@@ -211,10 +179,12 @@ static enum hrtimer_restart completion_timer_fire(struct hrtimer *timer) | |||
211 | /* Someone either beat us to the lock or hooked up a new server | 179 | /* Someone either beat us to the lock or hooked up a new server |
212 | * when we called server_completed. Rearm the timer. | 180 | * when we called server_completed. Rearm the timer. |
213 | */ | 181 | */ |
214 | if (domain->running[cpu] && !completion_timer->armed) { | 182 | if (domain->linked_servers[cpu] && !completion_timer->armed) { |
215 | server = domain->running[cpu]; | 183 | server = domain->linked_servers[cpu]; |
184 | |||
216 | TRACE_SUB(server, "rearming on P%d", cpu); | 185 | TRACE_SUB(server, "rearming on P%d", cpu); |
217 | budget_exhausted = server->start_time + server->budget; | 186 | |
187 | budget_exhausted = domain->start_times[cpu] + server->budget; | ||
218 | hrtimer_set_expires(timer, ns_to_ktime(budget_exhausted)); | 188 | hrtimer_set_expires(timer, ns_to_ktime(budget_exhausted)); |
219 | completion_timer->armed = 1; | 189 | completion_timer->armed = 1; |
220 | rv = HRTIMER_RESTART; | 190 | rv = HRTIMER_RESTART; |
@@ -222,7 +192,7 @@ static enum hrtimer_restart completion_timer_fire(struct hrtimer *timer) | |||
222 | completion_timer->armed = 0; | 192 | completion_timer->armed = 0; |
223 | } | 193 | } |
224 | 194 | ||
225 | raw_spin_unlock_irqrestore(domain->timer_lock, flags); | 195 | raw_spin_unlock_irqrestore(domain->completion_lock, flags); |
226 | 196 | ||
227 | return rv; | 197 | return rv; |
228 | } | 198 | } |
@@ -249,7 +219,8 @@ static void release_heap_free(server_release_heap_t* rh) | |||
249 | kmem_cache_free(server_release_cache, rh); | 219 | kmem_cache_free(server_release_cache, rh); |
250 | } | 220 | } |
251 | 221 | ||
252 | void server_init(server_t *server, int id, lt_t wcet, lt_t period, int grouped) | 222 | void server_init(server_t *server, server_domain_t *domain, |
223 | int id, lt_t wcet, lt_t period, int grouped) | ||
253 | { | 224 | { |
254 | server->id = id; | 225 | server->id = id; |
255 | server->wcet = wcet; | 226 | server->wcet = wcet; |
@@ -258,19 +229,18 @@ void server_init(server_t *server, int id, lt_t wcet, lt_t period, int grouped) | |||
258 | server->deadline = 0; | 229 | server->deadline = 0; |
259 | server->release = 0; | 230 | server->release = 0; |
260 | server->budget = 0; | 231 | server->budget = 0; |
261 | server->start_time = 0; | ||
262 | |||
263 | server->running = 0; | ||
264 | server->job_no = 0; | 232 | server->job_no = 0; |
265 | server->scheduled = NULL; | 233 | server->cpu = NO_CPU; |
234 | |||
235 | server->domain = domain; | ||
266 | 236 | ||
267 | server->data = NULL; | 237 | server->data = NULL; |
268 | 238 | ||
269 | server->hn = bheap_node_alloc(GFP_ATOMIC); | 239 | server->hn = bheap_node_alloc(GFP_ATOMIC); |
270 | bheap_node_init(&server->hn, server); | 240 | bheap_node_init(&server->hn, server); |
271 | INIT_LIST_HEAD(&server->list); | 241 | INIT_LIST_HEAD(&server->list); |
272 | server->release_heap = NULL; | ||
273 | 242 | ||
243 | server->release_heap = NULL; | ||
274 | if (grouped) { | 244 | if (grouped) { |
275 | server->release_heap = release_heap_alloc(GFP_ATOMIC); | 245 | server->release_heap = release_heap_alloc(GFP_ATOMIC); |
276 | INIT_LIST_HEAD(&server->release_list); | 246 | INIT_LIST_HEAD(&server->release_list); |
@@ -307,37 +277,58 @@ static inline lt_t lt_subtract(lt_t a, lt_t b) | |||
307 | return 0; | 277 | return 0; |
308 | } | 278 | } |
309 | 279 | ||
310 | void server_stop(server_t *server, server_domain_t *domain) | 280 | void server_run(server_t *server, struct task_struct *task) |
281 | { | ||
282 | int armed, cpu = task->rt_param.linked_on; | ||
283 | server_domain_t *domain = server->domain; | ||
284 | |||
285 | BUG_ON(is_server_linked(server)); | ||
286 | BUG_ON(server-> cpu != NO_CPU); | ||
287 | BUG_ON(cpu == NO_CPU); | ||
288 | BUG_ON(domain->linked_servers[cpu]); | ||
289 | BUG_ON(domain->linked_tasks[cpu]); | ||
290 | |||
291 | server->cpu = cpu; | ||
292 | domain->linked_servers[cpu] = server; | ||
293 | domain->linked_tasks[cpu] = task; | ||
294 | domain->start_times[cpu] = litmus_clock(); | ||
295 | armed = completion_timer_arm(domain, cpu); | ||
296 | domain->completion_timers[cpu].armed = armed; | ||
297 | |||
298 | TRACE_SUB(server, "running on cpu P%d", task->rt_param.linked_on); | ||
299 | } | ||
300 | |||
301 | void server_stop(server_t *server) | ||
311 | { | 302 | { |
312 | int cpu; | 303 | int cpu; |
313 | lt_t elapsed_time, now = litmus_clock(); | 304 | lt_t elapsed_time, now = litmus_clock(); |
305 | server_domain_t *domain = server->domain; | ||
314 | 306 | ||
315 | if (!server->running) { | 307 | if (!is_server_linked(server)) { |
316 | TRACE_SUB(server, "already stopped"); | 308 | TRACE_SUB(server, "already stopped"); |
317 | return; | 309 | return; |
318 | } | 310 | } |
319 | 311 | ||
320 | BUG_ON(!server->running); | 312 | cpu = server->cpu; |
321 | TRACE_SUB(server, "stopping server, start: %llu, end: %llu", | 313 | BUG_ON(cpu == NO_CPU); |
322 | server->start_time, now); | ||
323 | 314 | ||
315 | TRACE_SUB(server, "stopping server, start: %llu, end: %llu", | ||
316 | domain->start_times[cpu], now); | ||
324 | 317 | ||
325 | /* Calculate remaining budget */ | 318 | /* Calculate remaining budget */ |
326 | elapsed_time = lt_subtract(now, server->start_time); | 319 | elapsed_time = lt_subtract(now, domain->start_times[cpu]); |
327 | server->budget -= elapsed_time; | 320 | server->budget -= elapsed_time; |
328 | 321 | ||
322 | server->cpu = NO_CPU; | ||
323 | |||
329 | TRACE_SUB(server, "new budget: %llu", TIME(server->budget)); | 324 | TRACE_SUB(server, "new budget: %llu", TIME(server->budget)); |
325 | BUG_ON(domain->linked_servers[cpu] != server); | ||
330 | 326 | ||
331 | /* Set domain state */ | 327 | /* Set domain state */ |
332 | cpu = server->scheduled->rt_param.linked_on; | ||
333 | domain->completion_timers[cpu].armed = 0; | 328 | domain->completion_timers[cpu].armed = 0; |
334 | domain->running[cpu] = NULL; | 329 | domain->linked_servers[cpu] = NULL; |
330 | domain->linked_tasks[cpu] = NULL; | ||
335 | timer_cancel(&domain->completion_timers[cpu].timer); | 331 | timer_cancel(&domain->completion_timers[cpu].timer); |
336 | |||
337 | /* Make server inactive */ | ||
338 | server->running = 0; | ||
339 | server->scheduled = NULL; | ||
340 | server->start_time = 0; | ||
341 | } | 332 | } |
342 | 333 | ||
343 | void server_release(server_t *server) | 334 | void server_release(server_t *server) |
@@ -351,16 +342,12 @@ void server_release(server_t *server) | |||
351 | 342 | ||
352 | TRACE_SUB(server, "budget: %llu, release: %llu," | 343 | TRACE_SUB(server, "budget: %llu, release: %llu," |
353 | "deadline: %llu, period: %llu, job: %d", | 344 | "deadline: %llu, period: %llu, job: %d", |
354 | server->budget, server->release, server->deadline, | ||
355 | server->period, server->job_no); | ||
356 | TRACE_SUB(server, "budget: %llu, release: %llu," | ||
357 | "deadline: %llu, period: %llu, job: %d", | ||
358 | TIME(server->budget), TIME(server->release), TIME(server->deadline), | 345 | TIME(server->budget), TIME(server->release), TIME(server->deadline), |
359 | TIME(server->period), server->job_no); | 346 | TIME(server->period), server->job_no); |
360 | 347 | ||
361 | /* Need to reset for budget calculations */ | 348 | /* Need to reset for budget calculations */ |
362 | if (server->running) | 349 | if (is_server_linked(server)) |
363 | server->start_time = litmus_clock(); | 350 | server->domain->start_times[server->cpu] = litmus_clock(); |
364 | } | 351 | } |
365 | 352 | ||
366 | void server_release_at(server_t *server, lt_t time) | 353 | void server_release_at(server_t *server, lt_t time) |
@@ -379,34 +366,33 @@ static int server_proc_read(char* page, char **start, off_t off, | |||
379 | int count, int *eof, void *data) | 366 | int count, int *eof, void *data) |
380 | { | 367 | { |
381 | int length; | 368 | int length; |
382 | methods_t *methods = (methods_t*)data; | 369 | server_proc_t *proc = (server_proc_t*)data; |
383 | proc_read_args_t *args = kmalloc(sizeof(proc_read_args_t), | ||
384 | GFP_ATOMIC); | ||
385 | 370 | ||
386 | args->page = page; | 371 | proc->page = page; |
387 | args->length = 0; | 372 | proc->length = 0; |
388 | methods->list_servers(args); | 373 | proc->list_servers(proc); |
389 | 374 | ||
390 | length = args->length; | 375 | length = proc->length; |
391 | kfree(args); | ||
392 | *eof = 1; | 376 | *eof = 1; |
393 | 377 | ||
378 | proc->length = 0; | ||
379 | proc->page = NULL; | ||
380 | |||
394 | return length; | 381 | return length; |
395 | } | 382 | } |
396 | 383 | ||
397 | void server_proc_read_single(server_t *server, int cpu, | 384 | void list_server(server_t *server, int cpu, server_proc_t *proc) |
398 | struct proc_read_args *args) | ||
399 | { | 385 | { |
400 | if (cpu == NO_CPU) { | 386 | if (cpu == NO_CPU) { |
401 | args->length += | 387 | proc->length += |
402 | snprintf(args->page + args->length, | 388 | snprintf(proc->page + proc->length, |
403 | PAGE_SIZE - args->length, | 389 | PAGE_SIZE - proc->length, |
404 | "%8llu %8llu\n", | 390 | "%8llu %8llu\n", |
405 | server->wcet, server->period); | 391 | server->wcet, server->period); |
406 | } else { | 392 | } else { |
407 | args->length += | 393 | proc->length += |
408 | snprintf(args->page + args->length, | 394 | snprintf(proc->page + proc->length, |
409 | PAGE_SIZE - args->length, | 395 | PAGE_SIZE - proc->length, |
410 | "%8llu %8llu %3d\n", | 396 | "%8llu %8llu %3d\n", |
411 | server->wcet, server->period, cpu); | 397 | server->wcet, server->period, cpu); |
412 | } | 398 | } |
@@ -455,7 +441,7 @@ static inline int server_param_check(unsigned long long wcet, | |||
455 | static int server_proc_write(struct file *file, const char __user *input, | 441 | static int server_proc_write(struct file *file, const char __user *input, |
456 | unsigned long count, void *data) | 442 | unsigned long count, void *data) |
457 | { | 443 | { |
458 | methods_t *methods = (methods_t*)data; | 444 | server_proc_t *proc = (server_proc_t*)data; |
459 | #define SERVER_PROC_BUF 512 | 445 | #define SERVER_PROC_BUF 512 |
460 | char buffer[SERVER_PROC_BUF]; | 446 | char buffer[SERVER_PROC_BUF]; |
461 | unsigned long long wcet, period; | 447 | unsigned long long wcet, period; |
@@ -463,7 +449,7 @@ static int server_proc_write(struct file *file, const char __user *input, | |||
463 | int nums_converted, chars_seen, ret, cpu; | 449 | int nums_converted, chars_seen, ret, cpu; |
464 | 450 | ||
465 | /* Allow plugin to stop any running servers */ | 451 | /* Allow plugin to stop any running servers */ |
466 | methods->stop_servers(); | 452 | proc->stop_servers(); |
467 | 453 | ||
468 | if (count >= SERVER_PROC_BUF){ | 454 | if (count >= SERVER_PROC_BUF){ |
469 | printk(KERN_WARNING "proc buffer possibly too small in %s.\n", | 455 | printk(KERN_WARNING "proc buffer possibly too small in %s.\n", |
@@ -513,7 +499,7 @@ static int server_proc_write(struct file *file, const char __user *input, | |||
513 | ret = server_param_check(wcet, period, cpu); | 499 | ret = server_param_check(wcet, period, cpu); |
514 | if (ret) goto loop_end; | 500 | if (ret) goto loop_end; |
515 | 501 | ||
516 | ret = methods->admit_server(wcet, period, cpu); | 502 | ret = proc->admit_server(wcet, period, cpu); |
517 | if (ret) { | 503 | if (ret) { |
518 | printk(KERN_WARNING "Litmus plugin rejects server with " | 504 | printk(KERN_WARNING "Litmus plugin rejects server with " |
519 | "period: %llu, wcet: %llu, cpu: %d\n", | 505 | "period: %llu, wcet: %llu, cpu: %d\n", |
@@ -527,39 +513,46 @@ loop_end: | |||
527 | return count; | 513 | return count; |
528 | } | 514 | } |
529 | 515 | ||
530 | int server_proc_init(struct proc_dir_entry *proc_dir, char *file, | 516 | server_proc_t* server_proc_init(server_domain_t *domain, |
531 | admit_server_t admit_server, | 517 | struct proc_dir_entry *proc_dir, char *file, |
532 | list_servers_t list_servers, | 518 | admit_server_t admit_server, |
533 | stop_servers_t stop_servers) | 519 | list_servers_t list_servers, |
520 | stop_servers_t stop_servers) | ||
534 | { | 521 | { |
535 | int rv; | 522 | server_proc_t *server_proc = NULL; |
536 | methods_t *methods; | 523 | struct proc_dir_entry *entry; |
537 | struct proc_dir_entry *server_entry; | ||
538 | 524 | ||
539 | server_entry = create_proc_entry(file, 0644, proc_dir); | 525 | entry = create_proc_entry(file, 0644, proc_dir); |
540 | if (!server_entry) { | 526 | if (!entry) { |
541 | printk(KERN_ERR "Could not create proc entry: %s.\n", file); | 527 | printk(KERN_ERR "Could not create proc entry: %s.\n", file); |
542 | rv = -ENOENT; | ||
543 | goto out; | 528 | goto out; |
544 | } | 529 | } |
545 | 530 | ||
546 | /* Ack memory leak TODO */ | 531 | server_proc = kmalloc(sizeof(server_proc_t), GFP_ATOMIC); |
547 | methods = kmalloc(sizeof(methods_t), GFP_ATOMIC); | 532 | |
548 | methods->admit_server = admit_server; | 533 | entry->data = server_proc; |
549 | methods->list_servers = list_servers; | 534 | entry->read_proc = server_proc_read; |
550 | methods->stop_servers = stop_servers; | 535 | entry->write_proc = server_proc_write; |
551 | server_entry->data = methods; | 536 | |
537 | server_proc->entry = entry; | ||
538 | server_proc->admit_server = admit_server; | ||
539 | server_proc->list_servers = list_servers; | ||
540 | server_proc->stop_servers = stop_servers; | ||
541 | server_proc->length = 0; | ||
542 | server_proc->page = NULL; | ||
552 | 543 | ||
553 | server_entry->read_proc = server_proc_read; | 544 | INIT_LIST_HEAD(&server_proc->list); |
554 | server_entry->write_proc = server_proc_write; | 545 | list_add(&server_proc->list, &domain->server_procs); |
555 | 546 | ||
556 | out: | 547 | out: |
557 | return rv; | 548 | return server_proc; |
558 | } | 549 | } |
559 | 550 | ||
560 | void server_proc_exit(struct proc_dir_entry *proc_dir, char *file) | 551 | void server_proc_exit(server_proc_t *proc) |
561 | { | 552 | { |
562 | remove_proc_entry(file, proc_dir); | 553 | remove_proc_entry(proc->entry->name, proc->entry->parent); |
554 | list_del(&proc->list); | ||
555 | kfree(proc); | ||
563 | } | 556 | } |
564 | 557 | ||
565 | /****************************************************************************** | 558 | /****************************************************************************** |
@@ -569,7 +562,7 @@ void server_proc_exit(struct proc_dir_entry *proc_dir, char *file) | |||
569 | void server_domain_init(server_domain_t *domain, | 562 | void server_domain_init(server_domain_t *domain, |
570 | servers_released_t servers_released, | 563 | servers_released_t servers_released, |
571 | server_completed_t server_completed, | 564 | server_completed_t server_completed, |
572 | int release_master, raw_spinlock_t *timer_lock) | 565 | int release_master, raw_spinlock_t *completion_lock) |
573 | { | 566 | { |
574 | int i; | 567 | int i; |
575 | BUG_ON(!servers_released || !server_completed); | 568 | BUG_ON(!servers_released || !server_completed); |
@@ -582,17 +575,28 @@ void server_domain_init(server_domain_t *domain, | |||
582 | raw_spin_lock_init(&domain->tobe_lock); | 575 | raw_spin_lock_init(&domain->tobe_lock); |
583 | 576 | ||
584 | 577 | ||
585 | domain->release_master = release_master; | 578 | domain->release_master = release_master; |
586 | domain->timer_lock = timer_lock; | 579 | domain->completion_lock = completion_lock; |
587 | domain->server_completed = server_completed; | 580 | domain->server_completed = server_completed; |
588 | domain->servers_released = servers_released; | 581 | domain->servers_released = servers_released; |
589 | 582 | ||
590 | domain->completion_timers = kmalloc(NR_CPUS*sizeof(completion_timer_t), | 583 | INIT_LIST_HEAD(&domain->server_procs); |
591 | GFP_ATOMIC); | 584 | |
592 | domain->running = kmalloc(NR_CPUS*sizeof(server_t*), GFP_ATOMIC); | 585 | domain->completion_timers = |
586 | kmalloc(NR_CPUS*sizeof(completion_timer_t), GFP_ATOMIC); | ||
587 | domain->linked_servers = | ||
588 | kmalloc(NR_CPUS*sizeof(server_t*), GFP_ATOMIC); | ||
589 | domain->linked_tasks = | ||
590 | kmalloc(NR_CPUS*sizeof(struct task_struct*), GFP_ATOMIC); | ||
591 | domain->start_times = | ||
592 | kmalloc(NR_CPUS*sizeof(lt_t), GFP_ATOMIC); | ||
593 | 593 | ||
594 | for_each_online_cpu(i) { | 594 | for_each_online_cpu(i) { |
595 | domain->running[i] = NULL; | 595 | domain->linked_tasks[i] = NULL; |
596 | domain->linked_servers[i] = NULL; | ||
597 | domain->start_times[i] = 0; | ||
598 | |||
599 | /* Initialize the completion timer info */ | ||
596 | domain->completion_timers[i].armed = 0; | 600 | domain->completion_timers[i].armed = 0; |
597 | domain->completion_timers[i].cpu = i; | 601 | domain->completion_timers[i].cpu = i; |
598 | hrtimer_init(&domain->completion_timers[i].timer, | 602 | hrtimer_init(&domain->completion_timers[i].timer, |
@@ -607,8 +611,18 @@ void server_domain_init(server_domain_t *domain, | |||
607 | 611 | ||
608 | void server_domain_destroy(server_domain_t *domain) | 612 | void server_domain_destroy(server_domain_t *domain) |
609 | { | 613 | { |
614 | struct list_head *pos, *safe; | ||
615 | server_proc_t *proc; | ||
616 | |||
610 | kfree(domain->completion_timers); | 617 | kfree(domain->completion_timers); |
611 | kfree(domain->running); | 618 | kfree(domain->linked_tasks); |
619 | kfree(domain->linked_servers); | ||
620 | kfree(domain->start_times); | ||
621 | |||
622 | list_for_each_safe(pos, safe, &domain->server_procs) { | ||
623 | proc = list_entry(pos, server_proc_t, list); | ||
624 | server_proc_exit(proc); | ||
625 | } | ||
612 | } | 626 | } |
613 | 627 | ||
614 | static unsigned int time2slot(lt_t time) | 628 | static unsigned int time2slot(lt_t time) |
@@ -821,10 +835,11 @@ int add_server_release(server_t *server, server_domain_t *domain) | |||
821 | return arm_release_timer(domain); | 835 | return arm_release_timer(domain); |
822 | } | 836 | } |
823 | 837 | ||
824 | static void init_servers(void) | 838 | static int __init init_servers(void) |
825 | { | 839 | { |
826 | server_cache = KMEM_CACHE(server, SLAB_PANIC); | 840 | server_cache = KMEM_CACHE(server, SLAB_PANIC); |
827 | server_release_cache = KMEM_CACHE(server_release_heap, SLAB_PANIC); | 841 | server_release_cache = KMEM_CACHE(server_release_heap, SLAB_PANIC); |
842 | return 1; | ||
828 | } | 843 | } |
829 | 844 | ||
830 | static void exit_servers(void) | 845 | static void exit_servers(void) |