4 #include "kobject_helper.h"
7 class Scheduler : public Kobject_h<Scheduler>
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 // ----------------------------------------------------------------------------
45 #include "thread_object.h"
46 #include "l4_buf_iter.h"
47 #include "entry_frame.h"
49 FIASCO_DEFINE_KOBJ(Scheduler);
51 static Scheduler scheduler;
54 Scheduler::operator delete (void *)
56 printf("WARNING: tried to delete kernel scheduler object.\n"
57 " The system is now useless\n");
61 Scheduler::Scheduler()
63 initial_kobjects.register_obj(this, 7);
68 Scheduler::first_online(Cpu_set const *cpus, Mword bm)
70 unsigned cpu = cpus->offset();
74 unsigned b = (cpu - cpus->offset()) >> cpus->granularity();
75 if (cpu >= Config::Max_num_cpus || b >= MWORD_BITS)
78 if (!(bm & (1UL << b)))
80 cpu += 1UL << cpus->granularity();
93 Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb)
95 L4_msg_tag const tag = f->tag();
96 unsigned const curr_cpu = current_cpu();
98 Obj_space *s = current()->space()->obj_space();
99 L4_snd_item_iter snd_items(utcb, tag.words());
101 if (EXPECT_FALSE(tag.words() < 5))
102 return commit_result(-L4_err::EInval);
104 if (EXPECT_FALSE(!tag.items() || !snd_items.next()))
105 return commit_result(-L4_err::EInval);
107 L4_fpage _thread(snd_items.get()->d);
108 if (EXPECT_FALSE(!_thread.is_objpage()))
109 return commit_result(-L4_err::EInval);
111 Thread *thread = Kobject::dcast<Thread_object*>(s->lookup_local(_thread.obj_index()));
113 return commit_result(-L4_err::EInval);
115 Cpu_set const *cpus = reinterpret_cast<Cpu_set const *>(&utcb->values[1]);
117 Thread::Migration_info info;
119 unsigned t_cpu = thread->cpu();
120 if (cpus->contains(t_cpu, utcb->values[2]))
122 else if (cpus->contains(curr_cpu, utcb->values[2]))
125 info.cpu = first_online(cpus, utcb->values[2]);
127 if (info.cpu == Invalid_cpu)
128 return commit_result(-L4_err::EInval);
130 info.prio = utcb->values[3];
131 info.quantum = utcb->values[4];
133 printf("CPU[%lx]: current_cpu=%u run(thread=%lx, prio=%ld, quantum=%ld, cpu=%ld (%lx,%u,%u)\n",
134 dbg_id(), curr_cpu, thread->dbg_id(), info.prio, info.quantum, info.cpu, utcb->values[2], cpus->offset(), cpus->granularity());
140 info.quantum = Config::default_time_slice;
143 thread->migrate(info);
145 return commit_result(0);
150 Scheduler::sys_idle_time(unsigned char,
151 Syscall_frame *f, Utcb *utcb)
153 if (f->tag().words() < 3)
154 return commit_result(-L4_err::EInval);
156 Cpu_set const *cpus = reinterpret_cast<Cpu_set const *>(&utcb->values[1]);
157 Mword const cpu = first_online(cpus, utcb->values[2]);
159 return commit_result(-L4_err::EInval);
161 reinterpret_cast<Utcb::Time_val *>(utcb->values)->t
162 = Context::kernel_context(cpu)->consumed_time();
164 return commit_result(0, Utcb::Time_val::Words);
169 Scheduler::sys_info(unsigned char, Syscall_frame *f,
170 Utcb const *iutcb, Utcb *outcb)
172 if (f->tag().words() < 2)
173 return commit_result(-L4_err::EInval);
175 Cpu_set const *s = reinterpret_cast<Cpu_set const*>(&iutcb->values[1]);
177 Mword max = Config::Max_num_cpus;
178 Mword const offset = s->offset() << s->granularity();
180 return commit_result(-L4_err::EInval);
182 if (max > offset + ((Mword)MWORD_BITS << s->granularity()))
183 max = offset + ((Mword)MWORD_BITS << s->granularity());
185 for (Mword i = 0; i < max - offset; ++i)
186 if (Cpu::online(i + offset))
187 rm |= (1 << (i >> s->granularity()));
189 outcb->values[0] = rm;
190 outcb->values[1] = Config::Max_num_cpus;
191 return commit_result(0, 2);
196 Scheduler::kinvoke(L4_obj_ref, Mword rights, Syscall_frame *f,
197 Utcb const *iutcb, Utcb *outcb)
199 if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_cpu))
200 return commit_result(-L4_err::EBadproto);
202 switch (iutcb->values[0])
204 case Info: return sys_info(rights, f, iutcb, outcb);
205 case Run_thread: return sys_run(rights, f, iutcb);
206 case Idle_time: return sys_idle_time(rights, f, outcb);
207 default: return commit_result(-L4_err::ENosys);