4 #include "kobject_helper.h"
7 class Scheduler : public Kobject_h<Scheduler>, public Kobject
25 Mword offset() const { return (_w & 0x00ffffff) & (~0 << granularity()); }
26 Mword granularity() const { return (_w >> 24) & (MWORD_BITS-1) ; }
27 bool contains(unsigned cpu, Mword map) const
33 cpu >>= granularity();
34 if (cpu >= MWORD_BITS)
37 return map & (1UL << cpu);
42 // ----------------------------------------------------------------------------
46 #include "l4_buf_iter.h"
47 #include "entry_frame.h"
49 FIASCO_DEFINE_KOBJ(Scheduler);
51 static Scheduler scheduler;
54 Scheduler::Scheduler()
56 initial_kobjects.register_obj(this, 7);
61 Scheduler::first_online(Cpu_set const *cpus, Mword bm)
63 unsigned cpu = cpus->offset();
67 unsigned b = (cpu - cpus->offset()) >> cpus->granularity();
68 if (cpu >= Config::Max_num_cpus || b >= MWORD_BITS)
71 if (!(bm & (1UL << b)))
73 cpu += 1UL << cpus->granularity();
86 Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb)
88 L4_msg_tag const tag = f->tag();
89 unsigned const curr_cpu = current_cpu();
91 Obj_space *s = current()->space()->obj_space();
92 L4_snd_item_iter snd_items(utcb, tag.words());
94 if (EXPECT_FALSE(tag.words() < 5))
95 return commit_result(-L4_err::EInval);
97 if (EXPECT_FALSE(!tag.items() || !snd_items.next()))
98 return commit_result(-L4_err::EInval);
100 L4_fpage _thread(snd_items.get()->d);
101 if (EXPECT_FALSE(!_thread.is_objpage()))
102 return commit_result(-L4_err::EInval);
104 Thread *thread = Kobject::dcast<Thread*>(s->lookup_local(_thread.obj_index()));
106 return commit_result(-L4_err::EInval);
108 Cpu_set const *cpus = reinterpret_cast<Cpu_set const *>(&utcb->values[1]);
110 Thread::Migration_info info;
112 unsigned t_cpu = thread->cpu();
113 if (cpus->contains(t_cpu, utcb->values[2]))
115 else if (cpus->contains(curr_cpu, utcb->values[2]))
118 info.cpu = first_online(cpus, utcb->values[2]);
120 if (info.cpu == Invalid_cpu)
121 return commit_result(-L4_err::EInval);
123 info.prio = utcb->values[3];
124 info.quantum = utcb->values[4];
126 printf("CPU[%lx]: current_cpu=%u run(thread=%lx, prio=%ld, quantum=%ld, cpu=%ld (%lx,%u,%u)\n",
127 dbg_id(), curr_cpu, thread->dbg_id(), info.prio, info.quantum, info.cpu, utcb->values[2], cpus->offset(), cpus->granularity());
133 info.quantum = Config::default_time_slice;
136 thread->migrate(info);
138 return commit_result(0);
143 Scheduler::sys_idle_time(unsigned char,
144 Syscall_frame *f, Utcb *utcb)
146 if (f->tag().words() < 3)
147 return commit_result(-L4_err::EInval);
149 Cpu_set const *cpus = reinterpret_cast<Cpu_set const *>(&utcb->values[1]);
150 Mword const cpu = first_online(cpus, utcb->values[2]);
152 return commit_result(-L4_err::EInval);
154 reinterpret_cast<Utcb::Time_val *>(utcb->values)->t
155 = Context::kernel_context(cpu)->consumed_time();
157 return commit_result(0, Utcb::Time_val::Words);
162 Scheduler::sys_info(unsigned char, Syscall_frame *f,
163 Utcb const *iutcb, Utcb *outcb)
165 if (f->tag().words() < 2)
166 return commit_result(-L4_err::EInval);
168 Cpu_set const *s = reinterpret_cast<Cpu_set const*>(&iutcb->values[1]);
170 Mword max = Config::Max_num_cpus;
171 Mword const offset = s->offset() << s->granularity();
173 return commit_result(-L4_err::EInval);
175 if (max > offset + ((Mword)MWORD_BITS << s->granularity()))
176 max = offset + ((Mword)MWORD_BITS << s->granularity());
178 for (Mword i = 0; i < max - offset; ++i)
179 if (Cpu::online(i + offset))
180 rm |= (1 << (i >> s->granularity()));
182 outcb->values[0] = rm;
183 outcb->values[1] = Config::Max_num_cpus;
184 return commit_result(0, 2);
189 Scheduler::kinvoke(L4_obj_ref, Mword rights, Syscall_frame *f,
190 Utcb const *iutcb, Utcb *outcb)
192 if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_cpu))
193 return commit_result(-L4_err::EBadproto);
195 switch (iutcb->values[0])
197 case Info: return sys_info(rights, f, iutcb, outcb);
198 case Run_thread: return sys_run(rights, f, iutcb);
199 case Idle_time: return sys_idle_time(rights, f, outcb);
200 default: return commit_result(-L4_err::ENosys);