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