]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4sys/include/scheduler.h
d0e6502d2e3e708494d852b2487ade60cb664171
[l4.git] / l4 / pkg / l4sys / include / scheduler.h
1 /**
2  * \file
3  * \brief Scheduler object functions.
4  */
5 /*
6  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
7  *               Alexander Warg <warg@os.inf.tu-dresden.de>
8  *     economic rights: Technische Universität Dresden (Germany)
9  *
10  * This file is part of TUD:OS and distributed under the terms of the
11  * GNU General Public License 2.
12  * Please see the COPYING-GPL-2 file for details.
13  *
14  * As a special exception, you may use this file as part of a free software
15  * library without restriction.  Specifically, if other files instantiate
16  * templates or use macros or inline functions from this file, or you compile
17  * this file and link it with other files to produce an executable, this
18  * file does not by itself cause the resulting executable to be covered by
19  * the GNU General Public License.  This exception does not however
20  * invalidate any other reasons why the executable file might be covered by
21  * the GNU General Public License.
22  */
23 #pragma once
24
25 #include <l4/sys/kernel_object.h>
26 #include <l4/sys/ipc.h>
27
28 /**
29  * \defgroup l4_scheduler_api Scheduler
30  * \ingroup  l4_kernel_object_api
31  * \brief Scheduler object.
32  *
33  * <c>\#include <l4/sys/scheduler.h></c>
34  */
35
36 /**
37  * \brief
38  * \ingroup l4_scheduler_api
39  */
40 typedef struct l4_sched_cpu_set_t
41 {
42   /**
43    * First CPU of interest (must be aligned to 2^granularity).
44    */
45   l4_umword_t offset;
46
47   /**
48    * Bitmap of online CPUs.
49    */
50   l4_umword_t map;
51
52   /**
53    * One bit in map represents 2^granularity CPUs.
54    */
55   unsigned char granularity;
56
57 } l4_sched_cpu_set_t;
58
59 /**
60  * \brief
61  * \ingroup l4_scheduler_api
62  *
63  * \param offset       Offset.
64  * \param granularity  Granularitry in log2 notation.
65  * \param map          Bitmap of CPUs, defaults to 1 in C++.
66  *
67  * \return CPU set.
68  */
69 L4_INLINE l4_sched_cpu_set_t
70 l4_sched_cpu_set(l4_umword_t offset, unsigned char granularity,
71                  l4_umword_t map L4_DEFAULT_PARAM(1)) L4_NOTHROW;
72
73 /**
74  * \brief Get scheduler information.
75  * \ingroup l4_scheduler_api
76  *
77  * \param scheduler  Scheduler object.
78  * \retval cpu_max maximum number of CPUs ever available.
79  * \param cpus \a cpus.offset is first CPU of interest.
80  *             \a cpus.granularity (see l4_sched_cpu_set_t).
81  * \retval cpus \a cpus.map Bitmap of online CPUs.
82  *
83  * \return 0 on success, <0 error code otherwise.
84  */
85 L4_INLINE l4_msgtag_t
86 l4_scheduler_info(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
87                   l4_sched_cpu_set_t *cpus) L4_NOTHROW;
88
89 /**
90  * \internal
91  */
92 L4_INLINE l4_msgtag_t
93 l4_scheduler_info_u(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
94                     l4_sched_cpu_set_t *cpus, l4_utcb_t *utcb) L4_NOTHROW;
95
96
97 /**
98  * \brief
99  * \ingroup l4_scheduler_api
100  */
101 typedef struct l4_sched_param_t
102 {
103   /**
104    * Timeslice in micro seconds.
105    */
106   l4_cpu_time_t quantum;
107
108   /**
109    * Priority for scheduling.
110    */
111   unsigned prio;
112
113   /**
114    * CPU affinity.
115    */
116   l4_sched_cpu_set_t affinity;
117
118 } l4_sched_param_t;
119
120 /**
121  * \brief
122  * \ingroup l4_scheduler_api
123  */
124 L4_INLINE l4_sched_param_t
125 l4_sched_param(unsigned prio,
126                l4_cpu_time_t quantum L4_DEFAULT_PARAM(0)) L4_NOTHROW;
127
128 /**
129  * \brief Run a thread on a Scheduler.
130  * \ingroup l4_scheduler_api
131  *
132  * \param scheduler  Scheduler object.
133  * \param thread Thread to run.
134  * \param sp Scheduling parameters.
135  *
136  * \return 0 on success, <0 error code otherwise.
137  */
138 L4_INLINE l4_msgtag_t
139 l4_scheduler_run_thread(l4_cap_idx_t scheduler,
140                         l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW;
141
142 /**
143  * \internal
144  */
145 L4_INLINE l4_msgtag_t
146 l4_scheduler_run_thread_u(l4_cap_idx_t scheduler, l4_cap_idx_t thread,
147                           l4_sched_param_t const *sp, l4_utcb_t *utcb) L4_NOTHROW;
148
149 /**
150  * \brief Query idle time of a CPU, in µs.
151  * \ingroup l4_scheduler_api
152  *
153  * \param scheduler   Scheduler object.
154  * \param cpus        Set of CPUs to query.
155  *
156  * The consumed time is returned as l4_kernel_clock_t at UTCB message
157  * register 0.
158  */
159 L4_INLINE l4_msgtag_t
160 l4_scheduler_idle_time(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus) L4_NOTHROW;
161
162 /**
163  * \internal
164  */
165 L4_INLINE l4_msgtag_t
166 l4_scheduler_idle_time_u(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus,
167                          l4_utcb_t *utcb) L4_NOTHROW;
168
169
170
171 /**
172  * \brief Query if a CPU is online.
173  * \ingroup l4_scheduler_api
174  *
175  * \param scheduler  Scheduler object.
176  * \param cpu        CPU number.
177  * \return true if online, false if not (or any other query error).
178  */
179 L4_INLINE int
180 l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW;
181
182 /**
183  * \internal
184  */
185 L4_INLINE int
186 l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu,
187                          l4_utcb_t *utcb) L4_NOTHROW;
188
189
190
191 /**
192  * \brief Operations on the Scheduler object.
193  * \ingroup l4_scheduler_api
194  * \hideinitializer
195  * \internal
196  */
197 enum L4_cpu_ops
198 {
199   L4_SCHEDULER_INFO_OP       = 0UL, /**< Query infos about the scheduler */
200   L4_SCHEDULER_RUN_THREAD_OP = 1UL, /**< Run a thread on this scheduler */
201   L4_SCHEDULER_IDLE_TIME_OP  = 2UL, /**< Query idle time for the scheduler */
202 };
203
204 /*************** Implementations *******************/
205
206 L4_INLINE l4_sched_cpu_set_t
207 l4_sched_cpu_set(l4_umword_t offset, unsigned char granularity,
208                  l4_umword_t map) L4_NOTHROW
209 {
210   l4_sched_cpu_set_t cs;
211   cs.offset      = offset;
212   cs.granularity = granularity;
213   cs.map         = map;
214   return cs;
215 }
216
217 L4_INLINE l4_sched_param_t
218 l4_sched_param(unsigned prio, l4_cpu_time_t quantum) L4_NOTHROW
219 {
220   l4_sched_param_t sp;
221   sp.prio     = prio;
222   sp.quantum  = quantum;
223   sp.affinity = l4_sched_cpu_set(0, ~0, 1);
224   return sp;
225 }
226
227
228 L4_INLINE l4_msgtag_t
229 l4_scheduler_info_u(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
230                     l4_sched_cpu_set_t *cpus, l4_utcb_t *utcb) L4_NOTHROW
231 {
232   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
233   l4_msgtag_t res;
234
235   m->mr[0] = L4_SCHEDULER_INFO_OP;
236   m->mr[1] = (cpus->granularity << 24) | cpus->offset;
237
238   res = l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 2, 0, 0), L4_IPC_NEVER);
239
240   if (l4_msgtag_has_error(res))
241     return res;
242
243   cpus->map = m->mr[0];
244
245   if (cpu_max)
246     *cpu_max = m->mr[1];
247
248   return res;
249 }
250
251 L4_INLINE l4_msgtag_t
252 l4_scheduler_run_thread_u(l4_cap_idx_t scheduler, l4_cap_idx_t thread,
253                           l4_sched_param_t const *sp, l4_utcb_t *utcb) L4_NOTHROW
254 {
255   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
256   m->mr[0] = L4_SCHEDULER_RUN_THREAD_OP;
257   m->mr[1] = (sp->affinity.granularity << 24) | sp->affinity.offset;
258   m->mr[2] = sp->affinity.map;
259   m->mr[3] = sp->prio;
260   m->mr[4] = sp->quantum;
261   m->mr[5] = l4_map_obj_control(0, 0);
262   m->mr[6] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw;
263
264   return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 5, 1, 0), L4_IPC_NEVER);
265 }
266
267 L4_INLINE l4_msgtag_t
268 l4_scheduler_idle_time_u(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus,
269                          l4_utcb_t *utcb) L4_NOTHROW
270 {
271   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
272   v->mr[0] = L4_SCHEDULER_IDLE_TIME_OP;
273   v->mr[1] = (cpus->granularity << 24) | cpus->offset;
274   v->mr[2] = cpus->map;
275   return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 3, 0, 0), L4_IPC_NEVER);
276 }
277
278
279 L4_INLINE int
280 l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu,
281                          l4_utcb_t *utcb) L4_NOTHROW
282 {
283   l4_sched_cpu_set_t s;
284   l4_msgtag_t r;
285   s.offset = cpu;
286   s.granularity = 0;
287   r = l4_scheduler_info_u(scheduler, NULL, &s, utcb);
288   if (l4_msgtag_has_error(r) || l4_msgtag_label(r) < 0)
289     return 0;
290
291   return s.map & 1;
292 }
293
294
295 L4_INLINE l4_msgtag_t
296 l4_scheduler_info(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
297                   l4_sched_cpu_set_t *cpus) L4_NOTHROW
298 {
299   return l4_scheduler_info_u(scheduler, cpu_max, cpus, l4_utcb());
300 }
301
302 L4_INLINE l4_msgtag_t
303 l4_scheduler_run_thread(l4_cap_idx_t scheduler,
304                         l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW
305 {
306   return l4_scheduler_run_thread_u(scheduler, thread, sp, l4_utcb());
307 }
308
309 L4_INLINE l4_msgtag_t
310 l4_scheduler_idle_time(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus) L4_NOTHROW
311 {
312   return l4_scheduler_idle_time_u(scheduler, cpus, l4_utcb());
313 }
314
315 L4_INLINE int
316 l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW
317 {
318   return l4_scheduler_is_online_u(scheduler, cpu, l4_utcb());
319 }