]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4sys/include/scheduler.h
update
[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 CPU sets.
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 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 Scheduler parameter set.
99  * \ingroup l4_scheduler_api
100  */
101 typedef struct l4_sched_param_t
102 {
103   l4_cpu_time_t      quantum;  ///< Timeslice in micro seconds.
104   unsigned           prio;     ///< Priority for scheduling.
105   l4_sched_cpu_set_t affinity; ///< CPU affinity.
106 } l4_sched_param_t;
107
108 /**
109  * \brief Construct scheduler parameter.
110  * \ingroup l4_scheduler_api
111  */
112 L4_INLINE l4_sched_param_t
113 l4_sched_param(unsigned prio,
114                l4_cpu_time_t quantum L4_DEFAULT_PARAM(0)) L4_NOTHROW;
115
116 /**
117  * \brief Run a thread on a Scheduler.
118  * \ingroup l4_scheduler_api
119  *
120  * \param scheduler  Scheduler object.
121  * \param thread Thread to run.
122  * \param sp Scheduling parameters.
123  *
124  * \return 0 on success, <0 error code otherwise.
125  */
126 L4_INLINE l4_msgtag_t
127 l4_scheduler_run_thread(l4_cap_idx_t scheduler,
128                         l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW;
129
130 /**
131  * \internal
132  */
133 L4_INLINE l4_msgtag_t
134 l4_scheduler_run_thread_u(l4_cap_idx_t scheduler, l4_cap_idx_t thread,
135                           l4_sched_param_t const *sp, l4_utcb_t *utcb) L4_NOTHROW;
136
137 /**
138  * \brief Query idle time of a CPU, in µs.
139  * \ingroup l4_scheduler_api
140  *
141  * \param scheduler   Scheduler object.
142  * \param cpus        Set of CPUs to query.
143  *
144  * The consumed time is returned as l4_kernel_clock_t at UTCB message
145  * register 0.
146  */
147 L4_INLINE l4_msgtag_t
148 l4_scheduler_idle_time(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus) L4_NOTHROW;
149
150 /**
151  * \internal
152  */
153 L4_INLINE l4_msgtag_t
154 l4_scheduler_idle_time_u(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus,
155                          l4_utcb_t *utcb) L4_NOTHROW;
156
157
158
159 /**
160  * \brief Query if a CPU is online.
161  * \ingroup l4_scheduler_api
162  *
163  * \param scheduler  Scheduler object.
164  * \param cpu        CPU number.
165  * \return true if online, false if not (or any other query error).
166  */
167 L4_INLINE int
168 l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW;
169
170 /**
171  * \internal
172  */
173 L4_INLINE int
174 l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu,
175                          l4_utcb_t *utcb) L4_NOTHROW;
176
177
178
179 /**
180  * \brief Operations on the Scheduler object.
181  * \ingroup l4_scheduler_api
182  * \hideinitializer
183  * \internal
184  */
185 enum L4_scheduler_ops
186 {
187   L4_SCHEDULER_INFO_OP       = 0UL, /**< Query infos about the scheduler */
188   L4_SCHEDULER_RUN_THREAD_OP = 1UL, /**< Run a thread on this scheduler */
189   L4_SCHEDULER_IDLE_TIME_OP  = 2UL, /**< Query idle time for the scheduler */
190 };
191
192 /*************** Implementations *******************/
193
194 L4_INLINE l4_sched_cpu_set_t
195 l4_sched_cpu_set(l4_umword_t offset, unsigned char granularity,
196                  l4_umword_t map) L4_NOTHROW
197 {
198   l4_sched_cpu_set_t cs;
199   cs.offset      = offset;
200   cs.granularity = granularity;
201   cs.map         = map;
202   return cs;
203 }
204
205 L4_INLINE l4_sched_param_t
206 l4_sched_param(unsigned prio, l4_cpu_time_t quantum) L4_NOTHROW
207 {
208   l4_sched_param_t sp;
209   sp.prio     = prio;
210   sp.quantum  = quantum;
211   sp.affinity = l4_sched_cpu_set(0, ~0, 1);
212   return sp;
213 }
214
215
216 L4_INLINE l4_msgtag_t
217 l4_scheduler_info_u(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
218                     l4_sched_cpu_set_t *cpus, l4_utcb_t *utcb) L4_NOTHROW
219 {
220   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
221   l4_msgtag_t res;
222
223   m->mr[0] = L4_SCHEDULER_INFO_OP;
224   m->mr[1] = (cpus->granularity << 24) | cpus->offset;
225
226   res = l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 2, 0, 0), L4_IPC_NEVER);
227
228   if (l4_msgtag_has_error(res))
229     return res;
230
231   cpus->map = m->mr[0];
232
233   if (cpu_max)
234     *cpu_max = m->mr[1];
235
236   return res;
237 }
238
239 L4_INLINE l4_msgtag_t
240 l4_scheduler_run_thread_u(l4_cap_idx_t scheduler, l4_cap_idx_t thread,
241                           l4_sched_param_t const *sp, l4_utcb_t *utcb) L4_NOTHROW
242 {
243   l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
244   m->mr[0] = L4_SCHEDULER_RUN_THREAD_OP;
245   m->mr[1] = (sp->affinity.granularity << 24) | sp->affinity.offset;
246   m->mr[2] = sp->affinity.map;
247   m->mr[3] = sp->prio;
248   m->mr[4] = sp->quantum;
249   m->mr[5] = l4_map_obj_control(0, 0);
250   m->mr[6] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw;
251
252   return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 5, 1, 0), L4_IPC_NEVER);
253 }
254
255 L4_INLINE l4_msgtag_t
256 l4_scheduler_idle_time_u(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus,
257                          l4_utcb_t *utcb) L4_NOTHROW
258 {
259   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
260   v->mr[0] = L4_SCHEDULER_IDLE_TIME_OP;
261   v->mr[1] = (cpus->granularity << 24) | cpus->offset;
262   v->mr[2] = cpus->map;
263   return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 3, 0, 0), L4_IPC_NEVER);
264 }
265
266
267 L4_INLINE int
268 l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu,
269                          l4_utcb_t *utcb) L4_NOTHROW
270 {
271   l4_sched_cpu_set_t s;
272   l4_msgtag_t r;
273   s.offset = cpu;
274   s.granularity = 0;
275   r = l4_scheduler_info_u(scheduler, NULL, &s, utcb);
276   if (l4_msgtag_has_error(r) || l4_msgtag_label(r) < 0)
277     return 0;
278
279   return s.map & 1;
280 }
281
282
283 L4_INLINE l4_msgtag_t
284 l4_scheduler_info(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
285                   l4_sched_cpu_set_t *cpus) L4_NOTHROW
286 {
287   return l4_scheduler_info_u(scheduler, cpu_max, cpus, l4_utcb());
288 }
289
290 L4_INLINE l4_msgtag_t
291 l4_scheduler_run_thread(l4_cap_idx_t scheduler,
292                         l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW
293 {
294   return l4_scheduler_run_thread_u(scheduler, thread, sp, l4_utcb());
295 }
296
297 L4_INLINE l4_msgtag_t
298 l4_scheduler_idle_time(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus) L4_NOTHROW
299 {
300   return l4_scheduler_idle_time_u(scheduler, cpus, l4_utcb());
301 }
302
303 L4_INLINE int
304 l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW
305 {
306   return l4_scheduler_is_online_u(scheduler, cpu, l4_utcb());
307 }