]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/moe/server/src/sched_proxy.cc
Update
[l4.git] / l4 / pkg / l4re-core / moe / server / src / sched_proxy.cc
1 /*
2  * (c) 2009 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  */
9 #include "sched_proxy.h"
10 #include "globals.h"
11 #include "debug.h"
12
13 #include <algorithm>
14 #include <l4/re/env>
15 #include <l4/sys/scheduler>
16
17 //#include <cstdio>
18
19 static
20 l4_sched_cpu_set_t
21 blow_up(l4_sched_cpu_set_t const &src, unsigned char gran)
22 {
23   l4_sched_cpu_set_t n;
24   gran &= sizeof(l4_umword_t) * 8 - 1;
25   unsigned char og = src.granularity() & (sizeof(l4_umword_t) * 8 - 1);
26   n.set(gran, src.offset() & (~0UL << og));
27   n.map = 0;
28   for (unsigned i = 0; i < sizeof(l4_umword_t) * 8; ++i)
29     if (src.map & (1UL << (i >> (og - gran))))
30       n.map |= 1UL << i;
31
32   return n;
33 }
34
35 static
36 l4_sched_cpu_set_t operator & (l4_sched_cpu_set_t const &a, l4_sched_cpu_set_t const &b)
37 {
38   l4_sched_cpu_set_t _a, _b;
39   unsigned char const ga = a.granularity() & (sizeof(l4_umword_t) * 8 - 1);
40   unsigned char const gb = b.granularity() & (sizeof(l4_umword_t) * 8 - 1);
41   if (ga < gb)
42     {
43       _b = blow_up(b, ga);
44       _a = a;
45     }
46   else if (ga == gb)
47     {
48       _a = a;
49       _b = b;
50     }
51   else
52     {
53       _a = blow_up(a, gb);
54       _b = b;
55     }
56
57   long ofs_dif = _a.offset() - _b.offset();
58   long unsigned abs_ofs_dif;
59   if (ofs_dif < 0)
60     abs_ofs_dif = -ofs_dif;
61   else
62     abs_ofs_dif = ofs_dif;
63
64   if (abs_ofs_dif >= sizeof(l4_umword_t) * 8)
65     return l4_sched_cpu_set(0, 0, 0);
66
67   if (ofs_dif < 0)
68     {
69       _b.map &= (_a.map >> abs_ofs_dif);
70       return _b;
71     }
72   else
73     {
74       _a.map &= (_b.map >> abs_ofs_dif);
75       return _a;
76     }
77 }
78
79 Sched_proxy::List Sched_proxy::_list;
80
81 Sched_proxy::Sched_proxy() :
82   Icu(1, &_scheduler_irq),
83   _real_cpus(l4_sched_cpu_set(0, 0, 0)), _cpu_mask(_real_cpus),
84   _max_cpus(0),
85   _prio_offset(0), _prio_limit(0)
86 {
87   rescan_cpus();
88   _list.push_front(this);
89 }
90
91 void
92 Sched_proxy::rescan_cpus()
93 {
94   l4_sched_cpu_set_t c;
95   l4_umword_t max = 0;
96   c.map = 0;
97   c.gran_offset = 0;
98
99   int e = l4_error(L4Re::Env::env()->scheduler()->info(&max, &c));
100   if (e < 0)
101     return;
102
103   _max_cpus = std::min<unsigned>(sizeof(l4_umword_t) * 8, max);
104   _real_cpus = c;
105
106   _cpus = _real_cpus & _cpu_mask;
107 }
108
109 Sched_proxy::~Sched_proxy()
110 {
111   _list.remove(this);
112 }
113
114 int
115 Sched_proxy::info(l4_umword_t *cpu_max, l4_sched_cpu_set_t *cpus)
116 {
117   *cpu_max = _max_cpus;
118   unsigned char g = cpus->granularity() & (sizeof(l4_umword_t) * 8 - 1);
119   l4_umword_t offs = cpus->offset() & (~0UL << g);
120   if (offs >= _max_cpus)
121     return -L4_ERANGE;
122
123   cpus->map = 0;
124   unsigned b = 0;
125   for (unsigned i = offs; i < _max_cpus && b < sizeof(l4_umword_t) * 8;)
126     {
127       if (_cpus.map & (1UL << i))
128         cpus->map |= 1UL << b;
129
130       ++i;
131
132       if (!(i & ~(~0UL << g)))
133         ++b;
134     }
135
136   return L4_EOK;
137 }
138
139
140 int
141 Sched_proxy::run_thread(L4::Cap<L4::Thread> thread, l4_sched_param_t const &sp)
142 {
143   l4_sched_param_t s = sp;
144   s.prio = std::min(sp.prio + _prio_offset, (l4_umword_t)_prio_limit);
145   s.affinity = sp.affinity & _cpus;
146   if (0)
147     {
148       printf("loader[%p] run_thread: o=%u scheduler affinity = %lx "
149              "sp.m=%lx sp.o=%u sp.g=%u\n",
150              this, _cpus.offset(), _cpus.map, sp.affinity.map,
151              sp.affinity.offset(), sp.affinity.granularity());
152       printf("loader[%p]                                      "
153              " s.m=%lx  s.o=%u  s.g=%u\n",
154              this, s.affinity.map, s.affinity.offset(),
155              s.affinity.granularity());
156     }
157   return l4_error(L4Re::Env::env()->scheduler()->run_thread(thread, s));
158 }
159
160 int
161 Sched_proxy::idle_time(l4_sched_cpu_set_t const &, l4_kernel_clock_t &)
162 { return -L4_ENOSYS; }
163
164
165 L4::Cap<L4::Thread>
166 Sched_proxy::received_thread(L4::Ipc::Snd_fpage const &fp)
167 {
168   if (!fp.cap_received())
169     return L4::Cap<L4::Thread>::Invalid;
170
171   return L4::Cap<L4::Thread>(Rcv_cap << L4_CAP_SHIFT);
172 }
173
174 void
175 Sched_proxy::restrict_cpus(l4_umword_t cpus)
176 {
177   _cpu_mask = l4_sched_cpu_set(0, 0, cpus);
178   _cpus = _real_cpus & _cpu_mask;
179 }
180
181
182 class Cpu_hotplug_server :
183   public L4::Irqep_t<Cpu_hotplug_server, Moe::Server_object>
184 {
185 public:
186   void handle_irq()
187   {
188     for (auto i : Sched_proxy::_list)
189       {
190         i->rescan_cpus();
191         i->hotplug_event();
192       }
193   }
194
195   Cpu_hotplug_server()
196   {
197     L4::Cap<L4::Irq> irq = object_pool.cap_alloc()->alloc<L4::Irq>();
198     if (!irq)
199       {
200         Err(Err::Fatal).printf("Could not allocate capability for CPU hotplug\n");
201         return;
202       }
203
204     if (l4_error(L4::Cap<L4::Factory>(L4_BASE_FACTORY_CAP)->create(irq)) < 0)
205       {
206         Err(Err::Fatal).printf("Could not allocate IRQ for CPU hotplug\n");
207         return;
208       }
209
210     if (l4_error(irq->attach(l4_umword_t(this), L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP))) < 0)
211       {
212         Err(Err::Fatal).printf("Could not attach to CPU hotplug IRQ\n");
213         return;
214       }
215
216     if (l4_error(L4Re::Env::env()->scheduler()->bind(0, irq)) < 0)
217       {
218         Err(Err::Fatal).printf("Could not bind CPU hotplug IRQ to scheduler\n");
219         return;
220       }
221   }
222 };
223
224 static Cpu_hotplug_server _cpu_hotplug_server;