]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/moe/server/src/sched_proxy.cc
update
[l4.git] / l4 / pkg / 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.granularity = gran;
27   n.offset = src.offset & (~0UL << og);
28   n.map = 0;
29   for (unsigned i = 0; i < sizeof(l4_umword_t) * 8; ++i)
30     if (src.map & (1UL << (i >> (og - gran))))
31       n.map |= 1UL << i;
32
33   return n;
34 }
35
36 static
37 l4_sched_cpu_set_t operator & (l4_sched_cpu_set_t const &a, l4_sched_cpu_set_t const &b)
38 {
39   l4_sched_cpu_set_t _a, _b;
40   unsigned char const ga = a.granularity & (sizeof(l4_umword_t) * 8 - 1);
41   unsigned char const gb = b.granularity & (sizeof(l4_umword_t) * 8 - 1);
42   if (ga < gb)
43     {
44       _b = blow_up(b, ga);
45       _a = a;
46     }
47   else if (ga == gb)
48     {
49       _a = a;
50       _b = b;
51     }
52   else
53     {
54       _a = blow_up(a, gb);
55       _b = b;
56     }
57
58   long ofs_dif = _a.offset - _b.offset;
59   long unsigned abs_ofs_dif;
60   if (ofs_dif < 0)
61     abs_ofs_dif = -ofs_dif;
62   else
63     abs_ofs_dif = ofs_dif;
64
65   if (abs_ofs_dif >= sizeof(l4_umword_t) * 8)
66     return l4_sched_cpu_set(0,0,0);
67
68   if (ofs_dif < 0)
69     {
70       _b.map &= (_a.map >> abs_ofs_dif);
71       return _b;
72     }
73   else
74     {
75       _a.map &= (_b.map >> abs_ofs_dif);
76       return _a;
77     }
78 }
79
80 Sched_proxy::List Sched_proxy::_list;
81
82 Sched_proxy::Sched_proxy() :
83   Icu(1, &_scheduler_irq),
84   _real_cpus(l4_sched_cpu_set(0,0,0)), _cpu_mask(_real_cpus),
85   _max_cpus(0),
86   _prio_offset(0), _prio_limit(0)
87 {
88   rescan_cpus();
89   _list.push_front(this);
90 }
91
92 void
93 Sched_proxy::rescan_cpus()
94 {
95   l4_sched_cpu_set_t c;
96   l4_umword_t max = 0;
97   c.map = 0;
98   c.offset = 0;
99   c.granularity = 0;
100
101   int e = l4_error(L4Re::Env::env()->scheduler()->info(&max, &c));
102
103   if (e < 0)
104     return;
105
106   _max_cpus = std::min<unsigned>(sizeof(l4_umword_t) * 8, max);
107   _real_cpus = c;
108
109   _cpus = _real_cpus & _cpu_mask;
110 }
111
112 Sched_proxy::~Sched_proxy()
113 {
114   _list.remove(this);
115 }
116
117 int
118 Sched_proxy::info(l4_umword_t *cpu_max, l4_sched_cpu_set_t *cpus)
119 {
120   *cpu_max = _max_cpus;
121   unsigned char g = cpus->granularity & (sizeof(l4_umword_t) * 8 - 1);
122   l4_umword_t offs = cpus->offset & (~0UL << g);
123   if (offs >= _max_cpus)
124     return -L4_ERANGE;
125
126   cpus->map = 0;
127   unsigned b = 0;
128   for (unsigned i = offs; i < _max_cpus && b < sizeof(l4_umword_t) * 8;)
129     {
130       if (_cpus.map & (1UL << i))
131         cpus->map |= 1UL << b;
132
133       ++i;
134
135       if (!(i & ~(~0UL << g)))
136         ++b;
137     }
138
139   return L4_EOK;
140 }
141
142
143 int
144 Sched_proxy::run_thread(L4::Cap<L4::Thread> thread, l4_sched_param_t const &sp)
145 {
146   l4_sched_param_t s = sp;
147   s.prio = std::min(sp.prio + _prio_offset, _prio_limit);
148   s.affinity = sp.affinity & _cpus;
149 #if 0
150   printf("loader[%p] run_thread: o=%u scheduler affinity = %lx sp.m=%lx sp.o=%u sp.g=%u\n",
151       this, _cpus.offset, _cpus.map, sp.affinity.map, (unsigned)sp.affinity.offset, (unsigned)sp.affinity.granularity);
152   printf("loader[%p]                                      sp.m=%lx sp.o=%u sp.g=%u\n",
153       this, s.affinity.map, (unsigned)s.affinity.offset, (unsigned)s.affinity.granularity);
154 #endif
155   return l4_error(L4Re::Env::env()->scheduler()->run_thread(thread, s));
156 }
157
158 int
159 Sched_proxy::idle_time(l4_sched_cpu_set_t const &)
160 { return -L4_ENOSYS; }
161
162
163 L4::Cap<L4::Thread>
164 Sched_proxy::received_thread(L4::Ipc::Snd_fpage const &fp)
165 {
166   if (!fp.cap_received())
167     return L4::Cap<L4::Thread>::Invalid;
168
169   return L4::Cap<L4::Thread>(Rcv_cap << L4_CAP_SHIFT);
170 }
171
172 void
173 Sched_proxy::restrict_cpus(l4_umword_t cpus)
174 {
175   _cpu_mask = l4_sched_cpu_set(0, 0, cpus);
176   _cpus = _real_cpus & _cpu_mask;
177 }
178
179
180 class Cpu_hotplug_server : public Moe::Server_object
181 {
182 public:
183   int dispatch(l4_umword_t, L4::Ipc::Iostream &)
184   {
185     typedef Sched_proxy::List List;
186     for (List::Const_iterator i = Sched_proxy::_list.begin();
187          i != Sched_proxy::_list.end();
188          ++i)
189       {
190         i->rescan_cpus();
191         i->hotplug_event();
192       }
193     return 0;
194   }
195
196   Cpu_hotplug_server()
197   {
198     L4::Cap<L4::Irq> irq = object_pool.cap_alloc()->alloc<L4::Irq>();
199     if (!irq)
200       {
201         Err(Err::Fatal).printf("Could not allocate capability for CPU hotplug\n");
202         return;
203       }
204
205     if (l4_error(l4_factory_create_irq(L4_BASE_FACTORY_CAP, irq.cap())) < 0)
206       {
207         Err(Err::Fatal).printf("Could not allocate IRQ for CPU hotplug\n");
208         return;
209       }
210
211     if (l4_error(irq->attach( l4_umword_t(this), L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP))) < 0)
212       {
213         Err(Err::Fatal).printf("Could not attach to CPU hotplug IRQ\n");
214         return;
215       }
216
217     if (l4_error(L4Re::Env::env()->scheduler()->bind(0, irq)) < 0)
218       {
219         Err(Err::Fatal).printf("Could not bind CPU hotplug IRQ to scheduler\n");
220         return;
221       }
222   }
223 };
224
225 static Cpu_hotplug_server _cpu_hotplug_server;
226
227
228