3 * \brief Scheduler object functions.
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)
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.
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.
25 #include <l4/sys/kernel_object.h>
26 #include <l4/sys/ipc.h>
29 * \defgroup l4_scheduler_api Scheduler
30 * \ingroup l4_kernel_object_api
31 * \brief Scheduler object.
33 * <c>\#include <l4/sys/scheduler.h></c>
38 * \ingroup l4_scheduler_api
40 typedef struct l4_sched_cpu_set_t
43 * First CPU of interest (must be aligned to 2^granularity).
53 * One bit in #map represents 2^granularity CPUs.
55 unsigned char granularity;
61 * \ingroup l4_scheduler_api
63 * \param offset Offset.
64 * \param granularity Granularitry in log2 notation.
65 * \param map Bitmap of CPUs, defaults to 1 in C++.
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;
74 * \brief Get scheduler information.
75 * \ingroup l4_scheduler_api
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.
83 * \return 0 on success, <0 error code otherwise.
86 l4_scheduler_info(l4_cap_idx_t scheduler, l4_umword_t *cpu_max,
87 l4_sched_cpu_set_t *cpus) L4_NOTHROW;
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;
98 * \brief Scheduler parameter set.
99 * \ingroup l4_scheduler_api
101 typedef struct l4_sched_param_t
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.
109 * \brief Construct scheduler parameter.
110 * \ingroup l4_scheduler_api
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;
117 * \brief Run a thread on a Scheduler.
118 * \ingroup l4_scheduler_api
120 * \param scheduler Scheduler object.
121 * \param thread Thread to run.
122 * \param sp Scheduling parameters.
124 * \return 0 on success, <0 error code otherwise.
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;
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;
138 * \brief Query idle time of a CPU, in µs.
139 * \ingroup l4_scheduler_api
141 * \param scheduler Scheduler object.
142 * \param cpus Set of CPUs to query.
144 * The consumed time is returned as l4_kernel_clock_t at UTCB message
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;
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;
160 * \brief Query if a CPU is online.
161 * \ingroup l4_scheduler_api
163 * \param scheduler Scheduler object.
164 * \param cpu CPU number.
165 * \return true if online, false if not (or any other query error).
168 l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW;
174 l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu,
175 l4_utcb_t *utcb) L4_NOTHROW;
180 * \brief Operations on the Scheduler object.
181 * \ingroup l4_scheduler_api
185 enum L4_scheduler_ops
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 */
192 /*************** Implementations *******************/
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
198 l4_sched_cpu_set_t cs;
200 cs.granularity = granularity;
205 L4_INLINE l4_sched_param_t
206 l4_sched_param(unsigned prio, l4_cpu_time_t quantum) L4_NOTHROW
210 sp.quantum = quantum;
211 sp.affinity = l4_sched_cpu_set(0, ~0, 1);
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
220 l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
223 m->mr[0] = L4_SCHEDULER_INFO_OP;
224 m->mr[1] = (cpus->granularity << 24) | cpus->offset;
226 res = l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 2, 0, 0), L4_IPC_NEVER);
228 if (l4_msgtag_has_error(res))
231 cpus->map = m->mr[0];
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
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;
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;
252 return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 5, 1, 0), L4_IPC_NEVER);
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
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);
268 l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu,
269 l4_utcb_t *utcb) L4_NOTHROW
271 l4_sched_cpu_set_t s;
275 r = l4_scheduler_info_u(scheduler, NULL, &s, utcb);
276 if (l4_msgtag_has_error(r) || l4_msgtag_label(r) < 0)
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
287 return l4_scheduler_info_u(scheduler, cpu_max, cpus, l4_utcb());
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
294 return l4_scheduler_run_thread_u(scheduler, thread, sp, l4_utcb());
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
300 return l4_scheduler_idle_time_u(scheduler, cpus, l4_utcb());
304 l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW
306 return l4_scheduler_is_online_u(scheduler, cpu, l4_utcb());