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(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb)
55 L4_msg_tag const tag = f->tag();
56 unsigned 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 unsigned 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[%lx]: current_cpu=%u run(thread=%lx, cpu=%u (%lx,%lu,%lu)\n",
111 dbg_id(), curr_cpu, thread->dbg_id(), info.cpu,
112 utcb->values[2], sched_param->cpus.offset(), sched_param->cpus.granularity());
114 thread->migrate(&info);
116 return commit_result(0);
121 Scheduler::sys_idle_time(unsigned char,
122 Syscall_frame *f, Utcb *utcb)
124 if (f->tag().words() < 3)
125 return commit_result(-L4_err::EInval);
127 L4_cpu_set cpus = access_once(reinterpret_cast<L4_cpu_set const *>(&utcb->values[1]));
128 Mword const cpu = cpus.first(Cpu::online_mask(), Config::Max_num_cpus);
129 if (EXPECT_FALSE(cpu == Config::Max_num_cpus))
130 return commit_result(-L4_err::EInval);
132 reinterpret_cast<Utcb::Time_val *>(utcb->values)->t
133 = Context::kernel_context(cpu)->consumed_time();
135 return commit_result(0, Utcb::Time_val::Words);
140 Scheduler::sys_info(unsigned char, Syscall_frame *f,
141 Utcb const *iutcb, Utcb *outcb)
143 if (f->tag().words() < 2)
144 return commit_result(-L4_err::EInval);
146 L4_cpu_set_descr const s = access_once(reinterpret_cast<L4_cpu_set_descr const*>(&iutcb->values[1]));
148 Mword max = Config::Max_num_cpus;
149 Mword const offset = s.offset() << s.granularity();
151 return commit_result(-L4_err::EInval);
153 if (max > offset + ((Mword)MWORD_BITS << s.granularity()))
154 max = offset + ((Mword)MWORD_BITS << s.granularity());
156 for (Mword i = 0; i < max - offset; ++i)
157 if (Cpu::online(i + offset))
158 rm |= (1 << (i >> s.granularity()));
160 outcb->values[0] = rm;
161 outcb->values[1] = Config::Max_num_cpus;
162 return commit_result(0, 2);
167 Scheduler::icu_get_irq(unsigned irqnum)
177 Scheduler::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis)
179 *features = 0; // supported features (only normal irqs)
186 Scheduler::icu_bind_irq(Irq *irq_o, unsigned irqnum)
189 return commit_result(-L4_err::EInval);
194 Irq_chip_soft::bind(irq_o, irqnum);
196 return commit_result(0);
201 Scheduler::trigger_hotplug_event()
209 Scheduler::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
210 Utcb const *iutcb, Utcb *outcb)
212 switch (f->tag().proto())
214 case L4_msg_tag::Label_irq:
215 return Icu::icu_invoke(ref, rights, f, iutcb,outcb);
216 case L4_msg_tag::Label_scheduler:
219 return commit_result(-L4_err::EBadproto);
222 switch (iutcb->values[0])
224 case Info: return sys_info(rights, f, iutcb, outcb);
225 case Run_thread: return sys_run(rights, f, iutcb);
226 case Idle_time: return sys_idle_time(rights, f, outcb);
227 default: return commit_result(-L4_err::ENosys);