aboutsummaryrefslogtreecommitdiffstats
path: root/include/litmus/servers.h
blob: d3e45857653bb8c2eb271caff303fd8a8e90b71f (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#ifndef _LINUX_SERVERS_H_
#define _LINUX_SERVERS_H_

struct server;
struct periodic_server;
struct proc_dir_entry;
struct server_domain;
struct server_release_heap;
struct completion_timer;
struct server_proc;

#define SERVER_RELEASE_QUEUE_SLOTS 127

#define SERVER_FMT "{server/%d:%d}"
#define SERVER_ARGS(s) (s)->id, (s)->job_no

#define server_task(s) (((s)->cpu != NO_CPU)?s->domain->linked_tasks[(s)->cpu]:NULL)
#define is_server_linked(s) ((s)->cpu != NO_CPU)

/*
 * A single schedulable server.
 */
typedef struct server {
	/* Specified by the user */
	int 	id;
	lt_t 	wcet;
	lt_t	period;

	/* Optional */
	int 	type;
	void* 	data;

	/* Managed internally */
	lt_t	deadline;
	lt_t	release;
	lt_t	budget;	      /* The remaining budget for current period */
	int	job_no;       /* Current job of server */
	int	cpu;	      /* CPU the server is running on or NO_CPU */

	struct server_domain *domain;

	/* For membership in collections */
	struct bheap_node  *hn;
	struct list_head   list;

	/* Used for grouped releases */
	struct server_release_heap  *release_heap;
	struct list_head	    release_list;
} server_t;

/*
 * Called when a server exhausts its budget.
 */
typedef void (*server_completed_t)(struct server *server,
				   struct task_struct *was_running);
/*
 * Called when a group of servers release
 */
typedef void (*servers_released_t)(struct list_head *servers);
/*
 * Used to read server entries.
 */
typedef int (*admit_server_t)(unsigned long long wcet,
			      unsigned long long period, int cpu);
/*
 * Lists all servers for a proc entry by calling list_server on each.
 */
typedef void (*list_servers_t)(struct server_proc *proc);
/*
 * Stop all servers. Used to destroy servers on a proc entry rewrite.
 */
typedef void (*stop_servers_t)(void);

/*
 * Useful tools for scheduling servers.
 */
typedef struct server_domain {
	/* Collection of grouped releases */
	raw_spinlock_t		release_lock;
	struct list_head 	release_queue[SERVER_RELEASE_QUEUE_SLOTS];

	/* List of tasks to be added to the grouped releases */
	raw_spinlock_t		tobe_lock;
	struct list_head	tobe_released;

	/* CPU on which to release servers */
	int release_master;

	/* Per CPU information for running servers */
	struct completion_timer*	completion_timers;
	server_t**			linked_servers;
	struct task_struct**		linked_tasks;
	lt_t*				start_times;

	/* Used to lock firing of the completion timer.
	 * This is needed here and not for the release timer because
	 * the completion timer actually modifies the state of the
	 * server itself.
	 */
	raw_spinlock_t*			completion_lock;

	/* Event callbacks */
	server_completed_t		server_completed;
	servers_released_t		servers_released;

	/* Proc entries for controlling groups of servers */
	struct list_head	server_procs;
} server_domain_t;

/*
 * A group of servers releasing simultaneously.
 */
typedef struct server_release_heap {
	/* Servers to be released */
	struct list_head  servers;
	lt_t 		  release_time;

	/* For membership in the domain */
	struct list_head  list;

	/* For callbacks */
	server_domain_t	       *domain;

	struct hrtimer timer;
	struct hrtimer_start_on_info info;
} server_release_heap_t;

/*
 * A timer for managing server completions. Can be managed concurrently.
 */
typedef struct completion_timer {
	int 	armed; /* Is the timer armed or not? Seperate from the timer
			* so that it can be used to disarm a timer which
			* is already firing.
			*/
	int 	cpu;   /* CPU where the server is running. This is not the
			* cpu on which the timer will fire.
			*/
	struct hrtimer 			timer;
	struct hrtimer_start_on_info 	info;
	struct server_domain *domain; /* For callbacks */
} completion_timer_t;

/*
 * A proc directory entry which controls a group of servers.
 */
typedef struct server_proc {
	struct proc_dir_entry 	*entry;
	struct list_head 	list;
	admit_server_t admit_server;   /* Add a server from the entry	    */
	list_servers_t list_servers;   /* List each server in the entry     */
	stop_servers_t stop_servers;   /* Disables all servers in the entry */
        char* page;	/* Used internally by proc */
	int length;	/* Used internally by proc */
} server_proc_t;

/*
 * Initialize and exit servers
 */
void server_init(server_t *server, server_domain_t *domain, int id,
		 lt_t wcet, lt_t period, int grouped);
void server_destroy(server_t *server);

/*
 * Memory manage servers on the module slabs.
 */
server_t* server_alloc(int gfp_flags);
void server_free(server_t *server);

/*
 * Initialize and exit the server domain.
 */
void server_domain_init(server_domain_t *domain,
			servers_released_t servers_released,
			server_completed_t server_completed,
			int release_master, raw_spinlock_t* completion_lock);
void server_domain_destroy(server_domain_t *domain);

/*
 * Adds the next release of the server to the domain's timer.
 */
int add_server_release(server_t *server, server_domain_t *server_domain);

/*
 * Runs a task on the server.
 */
void server_run(server_t *server, struct task_struct *task);

/*
 * Stops server execution.
 */
void server_stop(server_t *server);

/*
 *  Begins a server's next period.
 */
void server_release(server_t *server);

/*
 * Set the next period to begin at the given time.
 */
void server_release_at(server_t *server, lt_t time);

/*
 * Call once for every server which should be printed by list_servers.
 */
void list_server(server_t *server, int cpu, server_proc_t *proc);

/*
 * Create and destroy a proc dir entry with the given file name.
 */
server_proc_t* server_proc_init(server_domain_t *domain,
				struct proc_dir_entry *proc_dir, char *file,
				admit_server_t admit_server,
				list_servers_t list_servers,
				stop_servers_t stop_servers);
void server_proc_exit(server_proc_t *proc);

#endif