4 #include "icu_helper.h"
7 class Scheduler : public Icu_h<Scheduler>, public Irq_chip_soft
10 typedef Icu_h<Scheduler> Icu;
20 static Scheduler scheduler;
25 // ----------------------------------------------------------------------------
28 #include "thread_object.h"
29 #include "l4_buf_iter.h"
31 #include "entry_frame.h"
33 FIASCO_DEFINE_KOBJ(Scheduler);
35 Scheduler Scheduler::scheduler;
38 Scheduler::operator delete (void *)
40 printf("WARNING: tried to delete kernel scheduler object.\n"
41 " The system is now useless\n");
45 Scheduler::Scheduler() : _irq(0)
47 initial_kobjects.register_obj(this, 7);
53 Scheduler::sys_run(L4_fpage::Rights, Syscall_frame *f, Utcb const *utcb)
55 L4_msg_tag const tag = f->tag();
56 Cpu_number const curr_cpu = current_cpu();
58 Obj_space *s = current()->space();
61 L4_snd_item_iter snd_items(utcb, tag.words());
63 if (EXPECT_FALSE(tag.words() < 5))
64 return commit_result(-L4_err::EInval);
66 unsigned long sz = sizeof (L4_sched_param_legacy);
69 L4_sched_param const *sched_param = reinterpret_cast<L4_sched_param const*>(&utcb->values[1]);
70 if (sched_param->sched_class < 0)
71 sz = sched_param->length;
73 sz += sizeof(Mword) - 1;
76 if (sz + 1 > tag.words())
77 return commit_result(-L4_err::EInval);
80 if (EXPECT_FALSE(!tag.items() || !snd_items.next()))
81 return commit_result(-L4_err::EInval);
83 L4_fpage _thread(snd_items.get()->d);
84 if (EXPECT_FALSE(!_thread.is_objpage()))
85 return commit_result(-L4_err::EInval);
87 Thread *thread = Kobject::dcast<Thread_object*>(s->lookup_local(_thread.obj_index()));
89 return commit_result(-L4_err::EInval);
93 memcpy(_store, &utcb->values[1], sz * sizeof(Mword));
95 L4_sched_param const *sched_param = reinterpret_cast<L4_sched_param const *>(_store);
97 Thread::Migration info;
99 Cpu_number const t_cpu = thread->cpu();
101 if (Cpu::online(t_cpu) && sched_param->cpus.contains(t_cpu))
103 else if (sched_param->cpus.contains(curr_cpu))
106 info.cpu = sched_param->cpus.first(Cpu::online_mask(), Config::max_num_cpus());
108 info.sp = sched_param;
110 printf("CPU[%u]: run(thread=%lx, cpu=%u (%lx,%u,%u)\n",
111 cxx::int_value<Cpu_number>(curr_cpu), thread->dbg_id(),
112 cxx::int_value<Cpu_number>(info.cpu),
114 cxx::int_value<Cpu_number>(sched_param->cpus.offset()),
115 cxx::int_value<Order>(sched_param->cpus.granularity()));
117 thread->migrate(&info);
119 return commit_result(0);
124 Scheduler::sys_idle_time(L4_fpage::Rights,
125 Syscall_frame *f, Utcb *utcb)
127 if (f->tag().words() < 3)
128 return commit_result(-L4_err::EInval);
130 L4_cpu_set cpus = access_once(reinterpret_cast<L4_cpu_set const *>(&utcb->values[1]));
131 Cpu_number const cpu = cpus.first(Cpu::online_mask(), Config::max_num_cpus());
132 if (EXPECT_FALSE(cpu == Config::max_num_cpus()))
133 return commit_result(-L4_err::EInval);
135 reinterpret_cast<Utcb::Time_val *>(utcb->values)->t
136 = Context::kernel_context(cpu)->consumed_time();
138 return commit_result(0, Utcb::Time_val::Words);
143 Scheduler::sys_info(L4_fpage::Rights, Syscall_frame *f,
144 Utcb const *iutcb, Utcb *outcb)
146 if (f->tag().words() < 2)
147 return commit_result(-L4_err::EInval);
149 L4_cpu_set_descr const s = access_once(reinterpret_cast<L4_cpu_set_descr const*>(&iutcb->values[1]));
151 Cpu_number max = Config::max_num_cpus();
152 Cpu_number const offset = s.offset() << s.granularity();
154 return commit_result(-L4_err::EInval);
156 if (max > offset + Cpu_number(MWORD_BITS) << s.granularity())
157 max = offset + Cpu_number(MWORD_BITS) << s.granularity();
159 for (Cpu_number i = Cpu_number::first(); i < max - offset; ++i)
160 if (Cpu::online(i + offset))
161 rm |= (1 << cxx::int_value<Cpu_number>(i >> s.granularity()));
163 outcb->values[0] = rm;
164 outcb->values[1] = Config::Max_num_cpus;
165 return commit_result(0, 2);
170 Scheduler::icu_get_irq(unsigned irqnum)
180 Scheduler::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis)
182 *features = 0; // supported features (only normal irqs)
189 Scheduler::icu_bind_irq(Irq *irq_o, unsigned irqnum)
192 return commit_result(-L4_err::EInval);
197 Irq_chip_soft::bind(irq_o, irqnum);
199 return commit_result(0);
204 Scheduler::icu_set_mode(Mword pin, Irq_chip::Mode)
207 return commit_result(-L4_err::EInval);
210 _irq->switch_mode(true);
211 return commit_result(0);
216 Scheduler::trigger_hotplug_event()
224 Scheduler::kinvoke(L4_obj_ref ref, L4_fpage::Rights rights, Syscall_frame *f,
225 Utcb const *iutcb, Utcb *outcb)
227 switch (f->tag().proto())
229 case L4_msg_tag::Label_irq:
230 return Icu::icu_invoke(ref, rights, f, iutcb,outcb);
231 case L4_msg_tag::Label_scheduler:
234 return commit_result(-L4_err::EBadproto);
237 switch (iutcb->values[0])
239 case Info: return sys_info(rights, f, iutcb, outcb);
240 case Run_thread: return sys_run(rights, f, iutcb);
241 case Idle_time: return sys_idle_time(rights, f, outcb);
242 default: return commit_result(-L4_err::ENosys);