1// vi:set ft=cpp: -*- Mode: C++ -*- 2/** 3 * \file 4 * Scheduler object functions. 5 */ 6/* 7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, 8 * Alexander Warg <warg@os.inf.tu-dresden.de> 9 * economic rights: Technische Universität Dresden (Germany) 10 * 11 * This file is part of TUD:OS and distributed under the terms of the 12 * GNU General Public License 2. 13 * Please see the COPYING-GPL-2 file for details. 14 * 15 * As a special exception, you may use this file as part of a free software 16 * library without restriction. Specifically, if other files instantiate 17 * templates or use macros or inline functions from this file, or you compile 18 * this file and link it with other files to produce an executable, this 19 * file does not by itself cause the resulting executable to be covered by 20 * the GNU General Public License. This exception does not however 21 * invalidate any other reasons why the executable file might be covered by 22 * the GNU General Public License. 23 */ 24#pragma once 25 26#include <l4/sys/icu> 27#include <l4/sys/scheduler.h> 28#include <l4/sys/capability> 29#include <l4/sys/cxx/ipc_iface> 30 31namespace L4 { 32 33/** 34 * C++ interface of the Scheduler kernel object. 35 * 36 * The Scheduler interface allows a client to manage CPU resources. The API 37 * provides functions to query scheduler information, check the online state of 38 * CPUs, query CPU idle time and to start threads on defined CPU sets. 39 * 40 * The scheduler offers IRQ number 0, which triggers when the number of online 41 * cores changes, e.g. due to hotplug events. 42 * 43 * The Scheduler interface inherits from L4::Icu and L4::Irq_eoi for managing 44 * the scheduler virtual device IRQ which, in contrast to hardware IRQs, 45 * implements a limited functionality: 46 * - Only IRQ line 0 is supported, no MSI vectors. 47 * - The IRQ is edge-triggered and the IRQ mode cannot be changed. 48 * - As the IRQ is edge-triggered, it does not have to be explicitly unmasked. 49 * 50 * \includefile{l4/sys/scheduler} 51 */ 52class L4_EXPORT Scheduler : 53 public Kobject_t<Scheduler, Icu, L4_PROTO_SCHEDULER, 54 Type_info::Demand_t<1> > 55{ 56public: 57 // ABI function for 'info' call 58 L4_INLINE_RPC_NF_OP(L4_SCHEDULER_INFO_OP, 59 l4_msgtag_t, info, (l4_umword_t gran_offset, l4_umword_t *map, 60 l4_umword_t *cpu_max)); 61 62 /** 63 * Get scheduler information. 64 * 65 * \param[out] cpu_max Maximum number of CPUs ever available. 66 * \param[in,out] cpus \a cpus.offset is first CPU of interest. 67 * \a cpus.granularity (see l4_sched_cpu_set_t). 68 * \a cpus.map Bitmap of online CPUs. 69 * \param utcb UTCB pointer of the calling thread. This defaults 70 * to the UTCB of the current thread. 71 * 72 * \retval 0 Success. 73 * \retval -L4_ERANGE The given CPU offset is larger than the maximum number 74 * of CPUs. 75 */ 76 l4_msgtag_t info(l4_umword_t *cpu_max, l4_sched_cpu_set_t *cpus, 77 l4_utcb_t *utcb = l4_utcb()) const noexcept 78 { 79 l4_umword_t max = 0; 80 l4_msgtag_t t = 81 info_t::call(c(), cpus->gran_offset, &cpus->map, &max, utcb); 82 if (cpu_max) *cpu_max = max; 83 return t; 84 } 85 86 /** 87 * Run a thread on a Scheduler. 88 * 89 * \param thread Capability of the thread to run. 90 * \param sp Scheduling parameters. 91 * 92 * \retval 0 Success. 93 * \retval -L4_EINVAL Invalid size of the scheduling parameter. 94 * 95 * This function launches a thread on a CPU determined by the scheduling 96 * parameter `sp.affinity`. A thread can be intentionally stopped by 97 * migrating it on an offline or an invalid CPU. The thread is only 98 * guaranteed to run if the CPU it is migrated to is currently online. 99 * 100 * \note A scheduler may impose a policy with regard to selecting CPUs. 101 * However the scheduler is required to ensure the following two properties: 102 * - Two threads with disjoint CPU sets must be scheduled to different 103 * physical CPUs. 104 * - Two threads with a single identical CPU selected in the CPU set must be 105 * scheduled to the same physical CPU. 106 */ 107 L4_INLINE_RPC_OP(L4_SCHEDULER_RUN_THREAD_OP, 108 l4_msgtag_t, run_thread, (Ipc::Cap<Thread> thread, l4_sched_param_t const &sp)); 109 110 /** 111 * Query the idle time (in µs) of a CPU. 112 * 113 * \param cpus Set of CPUs to query. Only the idle time of the first 114 * selected CPU in `cpus.map` is queried. 115 * \param[out] us Idle time of queried CPU in µs. 116 * 117 * \retval 0 Success. 118 * \retval -L4_EINVAL Invalid CPU requested in cpu set. 119 * 120 * This function retrieves the idle time in µs of the first selected 121 * CPU in `cpus.map`. The idle time is the accumulated time a CPU has spent in 122 * the idle thread since its last reset. To calculate a load estimate `l` one 123 * has to retrieve the idle time at the beginning (`i1`) and the end (`i2`) 124 * of a known time interval `t`. The load is then calculated as 125 * l = 1 - (i2 - i1)/t. 126 * 127 * The idle time is only defined for online CPUs. Reading the idle time from 128 * offline CPUs is undefined and may result in either getting -L4_EINVAL or 129 * calculating an estimated (incorrect) load of 1. 130 * 131 * \note The idle time statistics of remote CPUs is updated on context switch 132 * events only, hence may not be up-to-date when requested cross-CPU. To get 133 * up-to-date idle time you should use a thread running on the same CPU of 134 * which the idle time is requested. 135 */ 136 L4_INLINE_RPC_OP(L4_SCHEDULER_IDLE_TIME_OP, 137 l4_msgtag_t, idle_time, (l4_sched_cpu_set_t const &cpus, 138 l4_kernel_clock_t *us)); 139 140 /** 141 * Query if a CPU is online. 142 * 143 * \param cpu CPU number whose online status should be queried. 144 * \param utcb UTCB pointer of the calling thread. Defaults to \a l4_utcb(). 145 * 146 * \retval true The CPU is online. 147 * \retval false The CPU is offline 148 */ 149 bool is_online(l4_umword_t cpu, l4_utcb_t *utcb = l4_utcb()) const noexcept 150 { return l4_scheduler_is_online_u(cap(), cpu, utcb); } 151 152 typedef L4::Typeid::Rpcs_sys<info_t, run_thread_t, idle_time_t> Rpcs; 153}; 154} 155