]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/context.cpp
update
[l4.git] / kernel / fiasco / src / kern / context.cpp
1 INTERFACE:
2
3 #include <csetjmp>             // typedef jmp_buf
4 #include "types.h"
5 #include "clock.h"
6 #include "config.h"
7 #include "continuation.h"
8 #include "fpu_state.h"
9 #include "globals.h"
10 #include "l4_types.h"
11 #include "member_offs.h"
12 #include "per_cpu_data.h"
13 #include "queue.h"
14 #include "queue_item.h"
15 #include "rcupdate.h"
16 #include "sched_context.h"
17 #include "space.h"
18 #include "spin_lock.h"
19 #include "timeout.h"
20 #include <fiasco_defs.h>
21
22 class Entry_frame;
23 class Thread_lock;
24 class Context;
25 class Kobject_iface;
26
27 class Context_ptr
28 {
29 public:
30   explicit Context_ptr(Cap_index id) : _t(id) {}
31   Context_ptr() {}
32   Context_ptr(Context_ptr const &o) : _t(o._t) {}
33   Context_ptr const &operator = (Context_ptr const &o)
34   { _t = o._t; return *this; }
35
36   Kobject_iface *ptr(Space *, L4_fpage::Rights *) const;
37
38   bool is_kernel() const { return false; }
39   bool is_valid() const { return _t != Cap_index(~0UL); }
40
41   // only for debugging use
42   Cap_index raw() const { return _t; }
43
44 private:
45   Cap_index _t;
46
47 };
48
49 template< typename T >
50 class Context_ptr_base : public Context_ptr
51 {
52 public:
53   enum Invalid_type { Invalid };
54   enum Null_type { Null };
55   explicit Context_ptr_base(Invalid_type) : Context_ptr(Cap_index(~0UL)) {}
56   explicit Context_ptr_base(Null_type) : Context_ptr(Cap_index(0)) {}
57   explicit Context_ptr_base(Cap_index id) : Context_ptr(id) {}
58   Context_ptr_base() {}
59   Context_ptr_base(Context_ptr_base<T> const &o) : Context_ptr(o) {}
60   template< typename X >
61   Context_ptr_base(Context_ptr_base<X> const &o) : Context_ptr(o)
62   { X*x = 0; T*t = x; (void)t; }
63
64   Context_ptr_base<T> const &operator = (Context_ptr_base<T> const &o)
65   { Context_ptr::operator = (o); return *this; }
66
67   template< typename X >
68   Context_ptr_base<T> const &operator = (Context_ptr_base<X> const &o)
69   { X*x=0; T*t=x; (void)t; Context_ptr::operator = (o); return *this; }
70
71   //T *ptr(Space *s) const { return static_cast<T*>(Context_ptr::ptr(s)); }
72 };
73
74 class Context_space_ref
75 {
76 public:
77   typedef Spin_lock_coloc<Space *> Space_n_lock;
78
79 private:
80   Space_n_lock _s;
81   Address _v;
82
83 public:
84   Space *space() const { return _s.get_unused(); }
85   Space_n_lock *lock() { return &_s; }
86   Address user_mode() const { return _v & 1; }
87   Space *vcpu_user() const { return reinterpret_cast<Space*>(_v & ~3); }
88   Space *vcpu_aware() const { return user_mode() ? vcpu_user() : space(); }
89
90   void space(Space *s) { _s.set_unused(s); }
91   void vcpu_user(Space *s) { _v = (Address)s; }
92   void user_mode(bool enable)
93   {
94     if (enable)
95       _v |= (Address)1;
96     else
97       _v &= (Address)(~1);
98   }
99 };
100
101 /** An execution context.  A context is a runnable, schedulable activity.
102     It carries along some state used by other subsystems: A lock count,
103     and stack-element forward/next pointers.
104  */
105 class Context :
106   public Context_base,
107   protected Rcu_item
108 {
109   MEMBER_OFFSET();
110   friend class Jdb_thread_list;
111   friend class Context_ptr;
112   friend class Jdb_utcb;
113
114 protected:
115   virtual void finish_migration() = 0;
116   virtual bool initiate_migration() = 0;
117
118   struct State_request
119   {
120     Mword add;
121     Mword del;
122   };
123
124 public:
125   /**
126    * \brief Encapsulate an aggregate of Context.
127    *
128    * Allow to get a back reference to the aggregating Context object.
129    */
130   class Context_member
131   {
132   private:
133     Context_member(Context_member const &);
134
135   public:
136     Context_member() {}
137     /**
138      * \brief Get the aggregating Context object.
139      */
140     Context *context() const;
141   };
142
143   /**
144    * \brief Deffered Request.
145    *
146    * Represents a request that can be queued for each Context
147    * and is executed by the target context just after switching to the
148    * target context.
149    */
150   class Drq : public Queue_item, public Context_member
151   {
152   public:
153     typedef unsigned (Request_func)(Drq *, Context *target, void *);
154     enum { Need_resched = 1, No_answer = 2 };
155     enum Wait_mode { No_wait = 0, Wait = 1 };
156     enum Exec_mode { Target_ctxt = 0, Any_ctxt = 1 };
157     // enum State { Idle = 0, Handled = 1, Reply_handled = 2 };
158
159     Request_func *func;
160     Request_func *reply;
161     void *arg;
162     // State state;
163   };
164
165   /**
166    * \brief Queue for deffered requests (Drq).
167    *
168    * A FIFO queue each Context aggregates to queue incomming Drq's
169    * that have to be executed directly after switching to a context.
170    */
171   class Drq_q : public Queue, public Context_member
172   {
173   public:
174     enum Drop_mode { Drop = true, No_drop = false };
175     void enq(Drq *rq);
176     bool dequeue(Drq *drq, Queue_item::Status reason);
177     bool handle_requests(Drop_mode drop = No_drop);
178     bool execute_request(Drq *r, Drop_mode drop, bool local);
179   };
180
181   struct Migration
182   {
183     Cpu_number cpu;
184     L4_sched_param const *sp;
185     bool in_progress;
186
187     Migration() : in_progress(false) {}
188   };
189
190   template<typename T>
191   class Ku_mem_ptr : public Context_member
192   {
193     MEMBER_OFFSET();
194
195   private:
196     typename User<T>::Ptr _u;
197     T *_k;
198
199   public:
200     Ku_mem_ptr() : _u(0), _k(0) {}
201     Ku_mem_ptr(typename User<T>::Ptr const &u, T *k) : _u(u), _k(k) {}
202
203     void set(typename User<T>::Ptr const &u, T *k)
204     { _u = u; _k = k; }
205
206     T *access(bool is_current = false) const
207     {
208       // assert_kdb (!is_current || current() == context());
209       if (is_current
210           && (int)Config::Access_user_mem == Config::Access_user_mem_direct)
211         return _u.get();
212
213       Cpu_number const cpu = current_cpu();
214       if ((int)Config::Access_user_mem == Config::Must_access_user_mem_direct
215           && cpu == context()->cpu()
216           && Mem_space::current_mem_space(cpu) == context()->space())
217         return _u.get();
218       return _k;
219     }
220
221     typename User<T>::Ptr usr() const { return _u; }
222     T* kern() const { return _k; }
223   };
224
225 public:
226   /**
227    * Definition of different scheduling modes
228    */
229   enum Sched_mode
230   {
231     Periodic    = 0x1,  ///< 0 = Conventional, 1 = Periodic
232     Nonstrict   = 0x2,  ///< 0 = Strictly Periodic, 1 = Non-strictly periodic
233   };
234
235   /**
236    * Definition of different helping modes
237    */
238   enum Helping_mode
239   {
240     Helping,
241     Not_Helping,
242     Ignore_Helping
243   };
244
245   /**
246    * Return consumed CPU time.
247    * @return Consumed CPU time in usecs
248    */
249   Cpu_time consumed_time();
250
251   virtual bool kill() = 0;
252
253   void spill_user_state();
254   void fill_user_state();
255
256   Space * FIASCO_PURE space() const { return _space.space(); }
257   Mem_space * FIASCO_PURE mem_space() const { return static_cast<Mem_space*>(space()); }
258
259 protected:
260   /**
261    * Update consumed CPU time during each context switch and when
262    *        reading out the current thread's consumed CPU time.
263    */
264   void update_consumed_time();
265
266   Mword *_kernel_sp;
267   void *_utcb_handler;
268   Ku_mem_ptr<Utcb> _utcb;
269
270 private:
271   friend class Jdb;
272   friend class Jdb_tcb;
273
274   /// low level page table switching stuff
275   void switchin_context(Context *) asm ("switchin_context_label") FIASCO_FASTCALL;
276
277   /// low level fpu switching stuff
278   void switch_fpu(Context *t);
279
280   /// low level cpu switching stuff
281   void switch_cpu(Context *t);
282
283 protected:
284   Context_space_ref _space;
285
286 private:
287   Context *_donatee;
288   Context *_helper;
289
290   // Lock state
291   // how many locks does this thread hold on other threads
292   // incremented in Thread::lock, decremented in Thread::clear
293   // Thread::kill needs to know
294   int _lock_cnt;
295
296
297   // The scheduling parameters.  We would only need to keep an
298   // anonymous reference to them as we do not need them ourselves, but
299   // we aggregate them for performance reasons.
300   Sched_context _sched_context;
301   Sched_context *_sched;
302   Unsigned64 _period;
303   Sched_mode _mode;
304
305   // Pointer to floating point register state
306   Fpu_state _fpu_state;
307   // Implementation-specific consumed CPU time (TSC ticks or usecs)
308   Clock::Time _consumed_time;
309
310   Drq _drq;
311   Drq_q _drq_q;
312
313 protected:
314   // for trigger_exception
315   Continuation _exc_cont;
316
317   jmp_buf *_recover_jmpbuf;     // setjmp buffer for page-fault recovery
318
319   Migration *_migration;
320   bool _need_to_finish_migration;
321
322 public:
323   void arch_load_vcpu_kern_state(Vcpu_state *vcpu, bool do_load);
324
325 protected:
326   void arch_load_vcpu_user_state(Vcpu_state *vcpu, bool do_load);
327   void arch_update_vcpu_state(Vcpu_state *vcpu);
328
329   // XXX Timeout for both, sender and receiver! In normal case we would have
330   // to define own timeouts in Receiver and Sender but because only one
331   // timeout can be set at one time we use the same timeout. The timeout
332   // has to be defined here because Dirq::hit has to be able to reset the
333   // timeout (Irq::_irq_thread is of type Receiver).
334   Timeout *_timeout;
335
336 private:
337   static Per_cpu<Clock> _clock;
338   static Per_cpu<Context *> _kernel_ctxt;
339 };
340
341
342 INTERFACE [debug]:
343
344 #include "tb_entry.h"
345
346 EXTENSION class Context
347 {
348 public:
349   struct Drq_log : public Tb_entry
350   {
351     void *func;
352     void *reply;
353     Context *thread;
354     Drq const *rq;
355     Cpu_number target_cpu;
356     enum class Type { Send, Do_request, Do_reply, Done } type;
357     bool wait;
358     unsigned print(int max, char *buf) const;
359     Group_order has_partner() const
360     {
361       switch (type)
362         {
363         case Type::Send: return Group_order::first();
364         case Type::Done: return Group_order::last();
365         case Type::Do_request: return Group_order(1);
366         case Type::Do_reply: return Group_order(2);
367         }
368       return Group_order::none();
369     }
370
371     Group_order is_partner(Drq_log const *o) const
372     {
373       if (rq != o->rq || func != o->func || reply != o->reply)
374         return Group_order::none();
375
376       return o->has_partner();
377     }
378   };
379
380
381   struct Vcpu_log : public Tb_entry
382   {
383     Mword state;
384     Mword ip;
385     Mword sp;
386     Mword space;
387     Mword err;
388     unsigned char type;
389     unsigned char trap;
390     unsigned print(int max, char *buf) const;
391   };
392 };
393
394 // --------------------------------------------------------------------------
395 IMPLEMENTATION:
396
397 #include <cassert>
398 #include "atomic.h"
399 #include "cpu.h"
400 #include "cpu_lock.h"
401 #include "entry_frame.h"
402 #include "fpu.h"
403 #include "globals.h"            // current()
404 #include "kdb_ke.h"
405 #include "lock_guard.h"
406 #include "logdefs.h"
407 #include "mem.h"
408 #include "mem_layout.h"
409 #include "processor.h"
410 #include "space.h"
411 #include "std_macros.h"
412 #include "thread_state.h"
413 #include "timer.h"
414 #include "timeout.h"
415
416 DEFINE_PER_CPU Per_cpu<Clock> Context::_clock(true);
417 DEFINE_PER_CPU Per_cpu<Context *> Context::_kernel_ctxt;
418
419 IMPLEMENT inline NEEDS["kdb_ke.h"]
420 Kobject_iface * __attribute__((nonnull(1, 2)))
421 Context_ptr::ptr(Space *s, L4_fpage::Rights *rights) const
422 {
423   assert_kdb (cpu_lock.test());
424
425   return static_cast<Obj_space*>(s)->lookup_local(_t, rights);
426 }
427
428
429
430 #include <cstdio>
431
432 /** Initialize a context.  After setup, a switch_exec to this context results
433     in a return to user code using the return registers at regs().  The
434     return registers are not initialized however; neither is the space_context
435     to be used in thread switching (use set_space_context() for that).
436     @pre (_kernel_sp == 0)  &&  (* (stack end) == 0)
437     @param thread_lock pointer to lock used to lock this context
438     @param space_context the space context
439  */
440 PUBLIC inline NEEDS ["atomic.h", "entry_frame.h", <cstdio>]
441 Context::Context()
442 : _kernel_sp(reinterpret_cast<Mword*>(regs())),
443   _utcb_handler(0),
444   _helper(this),
445   _sched_context(),
446   _sched(&_sched_context),
447   _mode(Sched_mode(0)),
448   _migration(0),
449   _need_to_finish_migration(false)
450
451 {
452   // NOTE: We do not have to synchronize the initialization of
453   // _space_context because it is constant for all concurrent
454   // invocations of this constructor.  When two threads concurrently
455   // try to create a new task, they already synchronize in
456   // sys_task_new() and avoid calling us twice with different
457   // space_context arguments.
458
459   set_cpu_of(this, Cpu::invalid());
460 }
461
462 PUBLIC inline
463 void
464 Context::spill_fpu_if_owner()
465 {
466   // spill FPU state into memory before migration
467   if (state() & Thread_fpu_owner)
468     {
469       Fpu &f = Fpu::fpu.current();
470       if (current() != this)
471         f.enable();
472
473       spill_fpu();
474       f.set_owner(0);
475       f.disable();
476     }
477 }
478
479
480 PUBLIC inline
481 void
482 Context::do_kill()
483 {
484   // If this context owned the FPU, noone owns it now
485   Fpu &f = Fpu::fpu.current();
486   if (f.is_owner(this))
487     {
488       f.set_owner(0);
489       f.disable();
490     }
491 }
492
493 /** Destroy context.
494  */
495 PUBLIC virtual
496 Context::~Context()
497 {}
498
499 PUBLIC inline
500 bool
501 Context::check_for_current_cpu() const
502 {
503   bool r = cpu() == current_cpu() || !Cpu::online(cpu());
504   if (0 && EXPECT_FALSE(!r)) // debug output disabled
505     printf("FAIL: cpu=%u (current=%u)\n",
506            cxx::int_value<Cpu_number>(cpu()),
507            cxx::int_value<Cpu_number>(current_cpu()));
508   return r;
509 }
510
511
512 PUBLIC inline
513 Mword
514 Context::state(bool check = true) const
515 {
516   (void)check;
517   assert_kdb(!check || check_for_current_cpu());
518   return _state;
519 }
520
521 PUBLIC static inline
522 Context*
523 Context::kernel_context(Cpu_number cpu)
524 { return _kernel_ctxt.cpu(cpu); }
525
526 PROTECTED static inline
527 void
528 Context::kernel_context(Cpu_number cpu, Context *ctxt)
529 { _kernel_ctxt.cpu(cpu) = ctxt; }
530
531
532 /** @name State manipulation */
533 //@{
534 //-
535
536
537 /**
538  * Does the context exist? .
539  * @return true if this context has been initialized.
540  */
541 PUBLIC inline NEEDS ["thread_state.h"]
542 Mword
543 Context::exists() const
544 {
545   return state() != Thread_invalid;
546 }
547
548 /**
549  * Is the context about to be deleted.
550  * @return true if this context is in deletion.
551  */
552 PUBLIC inline NEEDS ["thread_state.h"]
553 bool
554 Context::is_invalid() const
555 { return state() == Thread_invalid; }
556
557 /**
558  * Atomically add bits to state flags.
559  * @param bits bits to be added to state flags
560  * @return 1 if none of the bits that were added had been set before
561  */
562 PUBLIC inline NEEDS ["atomic.h"]
563 void
564 Context::state_add(Mword bits)
565 {
566   assert_kdb(check_for_current_cpu());
567   atomic_or(&_state, bits);
568 }
569
570 /**
571  * Add bits in state flags. Unsafe (non-atomic) and
572  *        fast version -- you must hold the kernel lock when you use it.
573  * @pre cpu_lock.test() == true
574  * @param bits bits to be added to state flags
575  */ 
576 PUBLIC inline
577 void
578 Context::state_add_dirty(Mword bits, bool check = true)
579 {
580   (void)check;
581   assert_kdb(!check || check_for_current_cpu());
582   _state |= bits;
583 }
584
585 /**
586  * Atomically delete bits from state flags.
587  * @param bits bits to be removed from state flags
588  * @return 1 if all of the bits that were removed had previously been set
589  */
590 PUBLIC inline NEEDS ["atomic.h"]
591 void
592 Context::state_del(Mword bits)
593 {
594   assert_kdb (check_for_current_cpu());
595   atomic_and(&_state, ~bits);
596 }
597
598 /**
599  * Delete bits in state flags. Unsafe (non-atomic) and
600  *        fast version -- you must hold the kernel lock when you use it.
601  * @pre cpu_lock.test() == true
602  * @param bits bits to be removed from state flags
603  */
604 PUBLIC inline
605 void
606 Context::state_del_dirty(Mword bits, bool check = true)
607 {
608   (void)check;
609   assert_kdb(!check || check_for_current_cpu());
610   _state &= ~bits;
611 }
612
613 /**
614  * Atomically delete and add bits in state flags, provided the
615  *        following rules apply (otherwise state is not changed at all):
616  *        - Bits that are to be set must be clear in state or clear in mask
617  *        - Bits that are to be cleared must be set in state
618  * @param mask Bits not set in mask shall be deleted from state flags
619  * @param bits Bits to be added to state flags
620  * @return 1 if state was changed, 0 otherwise
621  */
622 PUBLIC inline NEEDS ["atomic.h"]
623 Mword
624 Context::state_change_safely(Mword mask, Mword bits)
625 {
626   assert_kdb (check_for_current_cpu());
627   Mword old;
628
629   do
630     {
631       old = _state;
632       if (old & bits & mask | ~old & ~mask)
633         return 0;
634     }
635   while (!cas(&_state, old, old & mask | bits));
636
637   return 1;
638 }
639
640 /**
641  * Atomically delete and add bits in state flags.
642  * @param mask bits not set in mask shall be deleted from state flags
643  * @param bits bits to be added to state flags
644  */
645 PUBLIC inline NEEDS ["atomic.h"]
646 Mword
647 Context::state_change(Mword mask, Mword bits)
648 {
649   assert_kdb (check_for_current_cpu());
650   return atomic_change(&_state, mask, bits);
651 }
652
653 /**
654  * Delete and add bits in state flags. Unsafe (non-atomic) and
655  *        fast version -- you must hold the kernel lock when you use it.
656  * @pre cpu_lock.test() == true
657  * @param mask Bits not set in mask shall be deleted from state flags
658  * @param bits Bits to be added to state flags
659  */
660 PUBLIC inline
661 void
662 Context::state_change_dirty(Mword mask, Mword bits, bool check = true)
663 {
664   (void)check;
665   assert_kdb(!check || check_for_current_cpu());
666   _state &= mask;
667   _state |= bits;
668 }
669
670 //@}
671 //-
672
673
674 PUBLIC inline
675 Context_space_ref *
676 Context::space_ref()
677 { return &_space; }
678
679 PUBLIC inline
680 Space *
681 Context::vcpu_aware_space() const
682 { return _space.vcpu_aware(); }
683
684 /** Registers used when iret'ing to user mode.
685     @return return registers
686  */
687 PUBLIC inline NEEDS["cpu.h", "entry_frame.h"]
688 Entry_frame *
689 Context::regs() const
690 {
691   return reinterpret_cast<Entry_frame *>
692     (Cpu::stack_align(reinterpret_cast<Mword>(this) + Size)) - 1;
693 }
694
695 /** @name Lock counting
696     These functions count the number of locks
697     this context holds.  A context must not be deleted if its lock
698     count is nonzero. */
699 //@{
700 //-
701
702 /** Increment lock count.
703     @post lock_cnt() > 0 */
704 PUBLIC inline
705 void
706 Context::inc_lock_cnt()
707 {
708   _lock_cnt++;
709 }
710
711 /** Decrement lock count.
712     @pre lock_cnt() > 0
713  */
714 PUBLIC inline
715 void
716 Context::dec_lock_cnt()
717 {
718   _lock_cnt--;
719 }
720
721 /** Lock count.
722     @return lock count
723  */
724 PUBLIC inline
725 int
726 Context::lock_cnt() const
727 {
728   return _lock_cnt;
729 }
730
731 //@}
732
733 /**
734  * Switch active timeslice of this Context.
735  * @param next Sched_context to switch to
736  */
737 PUBLIC
738 void
739 Context::switch_sched(Sched_context *next, Sched_context::Ready_queue *queue)
740 {
741   queue->switch_sched(sched(), next);
742   set_sched(next);
743 }
744
745 /**
746  * Select a different context for running and activate it.
747  */
748 PUBLIC
749 void
750 Context::schedule()
751 {
752   auto guard = lock_guard(cpu_lock);
753   assert (!Sched_context::rq.current().schedule_in_progress);
754
755   CNT_SCHEDULE;
756
757   // Ensure only the current thread calls schedule
758   assert_kdb (this == current());
759
760   Cpu_number current_cpu = Cpu_number::nil();
761   Sched_context::Ready_queue *rq = 0;
762
763   // Enqueue current thread into ready-list to schedule correctly
764   update_ready_list();
765
766   // Select a thread for scheduling.
767   Context *next_to_run;
768
769   do
770     {
771       // I may've been migrated during the switch_exec_locked in the while
772       // statement below. So check out if I've to use a new ready queue.
773         {
774           Cpu_number new_cpu = access_once(&_cpu);
775           if (new_cpu != current_cpu)
776             {
777               Mem::barrier();
778               current_cpu = new_cpu;
779               rq = &Sched_context::rq.current();
780               if (rq->schedule_in_progress)
781                 return;
782             }
783         }
784
785       for (;;)
786         {
787           next_to_run = rq->next_to_run()->context();
788
789           // Ensure ready-list sanity
790           assert_kdb (next_to_run);
791
792           if (EXPECT_TRUE (next_to_run->state() & Thread_ready_mask))
793             break;
794
795           rq->ready_dequeue(next_to_run->sched());
796
797           rq->schedule_in_progress = this;
798
799           cpu_lock.clear();
800           Proc::irq_chance();
801           cpu_lock.lock();
802
803           // check if we've been migrated meanwhile
804           if (EXPECT_FALSE(current_cpu != access_once(&_cpu)))
805             {
806               current_cpu = _cpu;
807               Mem::barrier();
808               rq = &Sched_context::rq.current();
809               if (rq->schedule_in_progress)
810                 return;
811             }
812           else
813             rq->schedule_in_progress = 0;
814         }
815     }
816   while (EXPECT_FALSE(schedule_switch_to_locked(next_to_run)));
817 }
818
819
820 PUBLIC inline
821 void
822 Context::schedule_if(bool s)
823 {
824   if (!s || Sched_context::rq.current().schedule_in_progress)
825     return;
826
827   schedule();
828 }
829
830
831 /**
832  * Return Context's Sched_context with id 'id'; return time slice 0 as default.
833  * @return Sched_context with id 'id' or 0
834  */
835 PUBLIC inline
836 Sched_context *
837 Context::sched_context(unsigned short const id = 0) const
838 {
839   if (EXPECT_TRUE (!id))
840     return const_cast<Sched_context*>(&_sched_context);
841 #if 0
842   for (Sched_context *tmp = _sched_context.next();
843       tmp != &_sched_context; tmp = tmp->next())
844     if (tmp->id() == id)
845       return tmp;
846 #endif
847   return 0;
848 }
849
850 /**
851  * Return Context's currently active Sched_context.
852  * @return Active Sched_context
853  */
854 PUBLIC inline
855 Sched_context *
856 Context::sched() const
857 {
858   return _sched;
859 }
860
861 /**
862  * Set Context's currently active Sched_context.
863  * @param sched Sched_context to be activated
864  */
865 PROTECTED inline
866 void
867 Context::set_sched(Sched_context * const sched)
868 {
869   _sched = sched;
870 }
871
872 /**
873  * Return Context's real-time period length.
874  * @return Period length in usecs
875  */
876 PUBLIC inline
877 Unsigned64
878 Context::period() const
879 {
880   return _period;
881 }
882
883 /**
884  * Set Context's real-time period length.
885  * @param period New period length in usecs
886  */
887 PROTECTED inline
888 void
889 Context::set_period(Unsigned64 const period)
890 {
891   _period = period;
892 }
893
894 /**
895  * Return Context's scheduling mode.
896  * @return Scheduling mode
897  */
898 PUBLIC inline
899 Context::Sched_mode
900 Context::mode() const
901 {
902   return _mode;
903 }
904
905 /**
906  * Set Context's scheduling mode.
907  * @param mode New scheduling mode
908  */
909 PUBLIC inline
910 void
911 Context::set_mode(Context::Sched_mode const mode)
912 {
913   _mode = mode;
914 }
915
916 // queue operations
917
918 // XXX for now, synchronize with global kernel lock
919 //-
920
921 /**
922  * Enqueue current() if ready to fix up ready-list invariant.
923  */
924 PRIVATE inline NOEXPORT
925 void
926 Context::update_ready_list()
927 {
928   assert_kdb (this == current());
929
930   if ((state() & Thread_ready_mask) && sched()->left())
931     Sched_context::rq.current().ready_enqueue(sched());
932 }
933
934 /**
935  * Check if Context is in ready-list.
936  * @return 1 if thread is in ready-list, 0 otherwise
937  */
938 PUBLIC inline
939 Mword
940 Context::in_ready_list() const
941 {
942   return sched()->in_ready_list();
943 }
944
945
946 /**
947  * \brief Activate a newly created thread.
948  *
949  * This function sets a new thread onto the ready list and switches to
950  * the thread if it can preempt the currently running thread.
951  */
952 PUBLIC
953 bool
954 Context::activate()
955 {
956   auto guard = lock_guard(cpu_lock);
957   if (cpu() == current_cpu())
958     {
959       state_add_dirty(Thread_ready);
960       if (Sched_context::rq.current().deblock(sched(), current()->sched(), true))
961         {
962           current()->switch_to_locked(this);
963           return true;
964         }
965     }
966   else
967     remote_ready_enqueue();
968
969   return false;
970 }
971
972
973 /** Helper.  Context that helps us by donating its time to us. It is
974     set by switch_exec() if the calling thread says so.
975     @return context that helps us and should be activated after freeing a lock.
976 */
977 PUBLIC inline
978 Context *
979 Context::helper() const
980 {
981   return _helper;
982 }
983
984
985 PUBLIC inline
986 void
987 Context::set_helper(Helping_mode const mode)
988 {
989   switch (mode)
990     {
991     case Helping:
992       _helper = current();
993       break;
994     case Not_Helping:
995       _helper = this;
996       break;
997     case Ignore_Helping:
998       // don't change _helper value
999       break;
1000     }
1001 }
1002
1003 /** Donatee.  Context that receives our time slices, for example
1004     because it has locked us.
1005     @return context that should be activated instead of us when we're
1006             switch_exec()'ed.
1007 */
1008 PUBLIC inline
1009 Context *
1010 Context::donatee() const
1011 {
1012   return _donatee;
1013 }
1014
1015 PUBLIC inline
1016 void
1017 Context::set_donatee(Context * const donatee)
1018 {
1019   _donatee = donatee;
1020 }
1021
1022 PUBLIC inline
1023 Mword *
1024 Context::get_kernel_sp() const
1025 {
1026   return _kernel_sp;
1027 }
1028
1029 PUBLIC inline
1030 void
1031 Context::set_kernel_sp(Mword * const esp)
1032 {
1033   _kernel_sp = esp;
1034 }
1035
1036 PUBLIC inline
1037 Fpu_state *
1038 Context::fpu_state()
1039 {
1040   return &_fpu_state;
1041 }
1042
1043 /**
1044  * Add to consumed CPU time.
1045  * @param quantum Implementation-specific time quantum (TSC ticks or usecs)
1046  */
1047 PUBLIC inline
1048 void
1049 Context::consume_time(Clock::Time quantum)
1050 {
1051   _consumed_time += quantum;
1052 }
1053
1054 /**
1055  * Update consumed CPU time during each context switch and when
1056  *        reading out the current thread's consumed CPU time.
1057  */
1058 IMPLEMENT inline NEEDS ["cpu.h"]
1059 void
1060 Context::update_consumed_time()
1061 {
1062   if (Config::Fine_grained_cputime)
1063     consume_time (_clock.cpu(cpu()).delta());
1064 }
1065
1066 IMPLEMENT inline NEEDS ["config.h", "cpu.h"]
1067 Cpu_time
1068 Context::consumed_time()
1069 {
1070   if (Config::Fine_grained_cputime)
1071     return _clock.cpu(cpu()).us(_consumed_time);
1072
1073   return _consumed_time;
1074 }
1075
1076 /**
1077  * Switch to scheduling context and execution context while not running under
1078  * CPU lock.
1079  */
1080 PUBLIC inline NEEDS [<cassert>]
1081 void
1082 Context::switch_to(Context *t)
1083 {
1084   // Call switch_to_locked if CPU lock is already held
1085   assert (!cpu_lock.test());
1086
1087   // Grab the CPU lock
1088   auto guard = lock_guard(cpu_lock);
1089
1090   switch_to_locked(t);
1091 }
1092
1093 /**
1094  * Switch scheduling context and execution context.
1095  * @param t Destination thread whose scheduling context and execution context
1096  *          should be activated.
1097  */
1098 PRIVATE inline NEEDS ["kdb_ke.h"]
1099 bool FIASCO_WARN_RESULT
1100 Context::schedule_switch_to_locked(Context *t)
1101 {
1102    // Must be called with CPU lock held
1103   assert_kdb (cpu_lock.test());
1104
1105   Sched_context::Ready_queue &rq = Sched_context::rq.current();
1106   // Switch to destination thread's scheduling context
1107   if (rq.current_sched() != t->sched())
1108     rq.set_current_sched(t->sched());
1109
1110   // XXX: IPC dependency tracking belongs here.
1111
1112   // Switch to destination thread's execution context, no helping involved
1113   if (t != this)
1114     return switch_exec_locked(t, Not_Helping);
1115
1116   return handle_drq();
1117 }
1118
1119 PUBLIC inline NEEDS [Context::schedule_switch_to_locked]
1120 void
1121 Context::switch_to_locked(Context *t)
1122 {
1123   if (EXPECT_FALSE(schedule_switch_to_locked(t)))
1124     schedule();
1125 }
1126
1127
1128 /**
1129  * Switch execution context while not running under CPU lock.
1130  */
1131 PUBLIC inline NEEDS ["kdb_ke.h"]
1132 bool FIASCO_WARN_RESULT
1133 Context::switch_exec(Context *t, enum Helping_mode mode)
1134 {
1135   // Call switch_exec_locked if CPU lock is already held
1136   assert_kdb (!cpu_lock.test());
1137
1138   // Grab the CPU lock
1139   auto guard = lock_guard(cpu_lock);
1140
1141   return switch_exec_locked(t, mode);
1142 }
1143
1144
1145 PRIVATE inline
1146 Context *
1147 Context::handle_helping(Context *t)
1148 {
1149   // XXX: maybe we do not need this on MP, because we have no helping there
1150   assert_kdb (current() == this);
1151   // Time-slice lending: if t is locked, switch to its locker
1152   // instead, this is transitive
1153   while (t->donatee() &&                // target thread locked
1154          t->donatee() != t)             // not by itself
1155     {
1156       // Special case for Thread::kill(): If the locker is
1157       // current(), switch to the locked thread to allow it to
1158       // release other locks.  Do this only when the target thread
1159       // actually owns locks.
1160       if (t->donatee() == this)
1161         {
1162           if (t->lock_cnt() > 0)
1163             break;
1164
1165           return this;
1166         }
1167
1168       t = t->donatee();
1169     }
1170   return t;
1171 }
1172
1173
1174 /**
1175  * Switch to a specific different execution context.
1176  *        If that context is currently locked, switch to its locker instead
1177  *        (except if current() is the locker)
1178  * @pre current() == this  &&  current() != t
1179  * @param t thread that shall be activated.
1180  * @param mode helping mode; we either help, don't help or leave the
1181  *             helping state unchanged
1182  */
1183 PUBLIC
1184 bool  FIASCO_WARN_RESULT //L4_IPC_CODE
1185 Context::switch_exec_locked(Context *t, enum Helping_mode mode)
1186 {
1187   // Must be called with CPU lock held
1188   assert_kdb (t->cpu() != Cpu::invalid());
1189   assert_kdb (t->cpu() == current_cpu());
1190   assert_kdb (cpu() == current_cpu());
1191   assert_kdb (cpu_lock.test());
1192   assert_kdb (current() != t);
1193   assert_kdb (current() == this);
1194   assert_kdb (timeslice_timeout.cpu(cpu())->is_set()); // Coma check
1195
1196   // only for logging
1197   Context *t_orig = t;
1198   (void)t_orig;
1199
1200   // Time-slice lending: if t is locked, switch to its locker
1201   // instead, this is transitive
1202   t = handle_helping(t);
1203
1204   if (t == this)
1205     return handle_drq();
1206
1207   LOG_CONTEXT_SWITCH;
1208   CNT_CONTEXT_SWITCH;
1209
1210   // Can only switch to ready threads!
1211   if (EXPECT_FALSE (!(t->state() & Thread_ready_mask)))
1212     {
1213       assert_kdb (state() & Thread_ready_mask);
1214       return false;
1215     }
1216
1217
1218   // Ensure kernel stack pointer is non-null if thread is ready
1219   assert_kdb (t->_kernel_sp);
1220
1221   t->set_helper(mode);
1222
1223   update_ready_list();
1224   assert_kdb (!(state() & Thread_ready_mask) || !sched()->left()
1225               || in_ready_list());
1226
1227   switch_fpu(t);
1228   switch_cpu(t);
1229
1230   return handle_drq();
1231 }
1232
1233 PUBLIC inline NEEDS[Context::switch_exec_locked, Context::schedule]
1234 void
1235 Context::switch_exec_schedule_locked(Context *t, enum Helping_mode mode)
1236 {
1237   if (EXPECT_FALSE(switch_exec_locked(t, mode)))
1238     schedule();
1239 }
1240
1241 PUBLIC inline
1242 Context::Ku_mem_ptr<Utcb> const &
1243 Context::utcb() const
1244 { return _utcb; }
1245
1246 IMPLEMENT inline NEEDS["globals.h"]
1247 Context *
1248 Context::Context_member::context() const
1249 { return context_of(this); }
1250
1251 IMPLEMENT inline NEEDS["lock_guard.h", "kdb_ke.h"]
1252 void
1253 Context::Drq_q::enq(Drq *rq)
1254 {
1255   assert_kdb(cpu_lock.test());
1256   auto guard = lock_guard(q_lock());
1257   enqueue(rq);
1258 }
1259
1260 PRIVATE inline
1261 bool
1262 Context::do_drq_reply(Drq *r, Drq_q::Drop_mode drop)
1263 {
1264   state_change_dirty(~Thread_drq_wait, Thread_ready);
1265   // r->state = Drq::Reply_handled;
1266   if (drop == Drq_q::No_drop && r->reply)
1267     return r->reply(r, this, r->arg) & Drq::Need_resched;
1268
1269   return false;
1270 }
1271
1272 IMPLEMENT inline NEEDS[Context::do_drq_reply]
1273 bool
1274 Context::Drq_q::execute_request(Drq *r, Drop_mode drop, bool local)
1275 {
1276   bool need_resched = false;
1277   Context *const self = context();
1278   // printf("CPU[%2u:%p]: context=%p: handle request for %p (func=%p, arg=%p)\n", current_cpu(), current(), context(), r->context(), r->func, r->arg);
1279   if (r->context() == self)
1280     {
1281       LOG_TRACE("DRQ handling", "drq", current(), Drq_log,
1282           l->type = Drq_log::Type::Do_reply;
1283           l->rq = r;
1284           l->func = (void*)r->func;
1285           l->reply = (void*)r->reply;
1286           l->thread = r->context();
1287           l->target_cpu = current_cpu();
1288           l->wait = 0;
1289       );
1290       //LOG_MSG_3VAL(current(), "hrP", current_cpu() | (drop ? 0x100: 0), (Mword)r->context(), (Mword)r->func);
1291       return self->do_drq_reply(r, drop);
1292     }
1293   else
1294     {
1295       LOG_TRACE("DRQ handling", "drq", current(), Drq_log,
1296           l->type = Drq_log::Type::Do_request;
1297           l->rq = r;
1298           l->func = (void*)r->func;
1299           l->reply = (void*)r->reply;
1300           l->thread = r->context();
1301           l->target_cpu = current_cpu();
1302           l->wait = 0;
1303       );
1304       // r->state = Drq::Idle;
1305       unsigned answer = 0;
1306       //LOG_MSG_3VAL(current(), "hrq", current_cpu() | (drop ? 0x100: 0), (Mword)r->context(), (Mword)r->func);
1307       if (EXPECT_TRUE(drop == No_drop && r->func))
1308         answer = r->func(r, self, r->arg);
1309       else if (EXPECT_FALSE(drop == Drop))
1310         // flag DRQ abort for requester
1311         r->arg = (void*)-1;
1312        // LOG_MSG_3VAL(current(), "hrq-", answer, current()->state() /*(Mword)r->context()*/, (Mword)r->func);
1313       need_resched |= answer & Drq::Need_resched;
1314       //r->state = Drq::Handled;
1315
1316       // enqueue answer
1317       if (!(answer & Drq::No_answer))
1318         {
1319           if (local)
1320             return r->context()->do_drq_reply(r, drop) || need_resched;
1321           else
1322             need_resched |= r->context()->enqueue_drq(r, Drq::Target_ctxt);
1323         }
1324     }
1325   return need_resched;
1326 }
1327
1328 IMPLEMENT inline NEEDS["lock_guard.h"]
1329 bool
1330 Context::Drq_q::dequeue(Drq *drq, Queue_item::Status reason)
1331 {
1332   auto guard = lock_guard(q_lock());
1333   if (!drq->queued())
1334     return false;
1335   return Queue::dequeue(drq, reason);
1336 }
1337
1338 IMPLEMENT inline NEEDS["mem.h", "lock_guard.h"]
1339 bool
1340 Context::Drq_q::handle_requests(Drop_mode drop)
1341 {
1342   // printf("CPU[%2u:%p]: > Context::Drq_q::handle_requests() context=%p\n", current_cpu(), current(), context());
1343   bool need_resched = false;
1344   while (1)
1345     {
1346       Queue_item *qi;
1347         {
1348           auto guard = lock_guard(q_lock());
1349           qi = first();
1350           if (!qi)
1351             return need_resched;
1352
1353           check_kdb (Queue::dequeue(qi, Queue_item::Ok));
1354         }
1355
1356       Drq *r = static_cast<Drq*>(qi);
1357       // printf("CPU[%2u:%p]: context=%p: handle request for %p (func=%p, arg=%p)\n", current_cpu(), current(), context(), r->context(), r->func, r->arg);
1358       need_resched |= execute_request(r, drop, false);
1359     }
1360 }
1361 /**
1362  * \biref Forced dequeue from lock wait queue, or DRQ queue.
1363  */
1364 PRIVATE
1365 void
1366 Context::force_dequeue()
1367 {
1368   Queue_item *const qi = queue_item();
1369
1370   if (qi->queued())
1371     {
1372       // we're waiting for a lock or have a DRQ pending
1373       Queue *const q = qi->queue();
1374         {
1375           auto guard = lock_guard(q->q_lock());
1376           // check again, with the queue lock held.
1377           // NOTE: we may be already removed from the queue on another CPU
1378           if (qi->queued() && qi->queue())
1379             {
1380               // we must never be taken from one queue to another on a
1381               // different CPU
1382               assert_kdb(q == qi->queue());
1383               // pull myself out of the queue, mark reason as invalidation
1384               q->dequeue(qi, Queue_item::Invalid);
1385             }
1386         }
1387     }
1388 }
1389
1390 /**
1391  * \brief Dequeue from lock and DRQ queues, abort pending DRQs
1392  */
1393 PROTECTED
1394 void
1395 Context::shutdown_queues()
1396 {
1397   force_dequeue();
1398   shutdown_drqs();
1399 }
1400
1401
1402 /**
1403  * \brief Check for pending DRQs.
1404  * \return true if there are DRQs pending, false if not.
1405  */
1406 PUBLIC inline
1407 bool
1408 Context::drq_pending() const
1409 { return _drq_q.first(); }
1410
1411 PUBLIC inline
1412 void
1413 Context::try_finish_migration()
1414 {
1415   if (EXPECT_FALSE(_need_to_finish_migration))
1416     {
1417       _need_to_finish_migration = false;
1418       finish_migration();
1419     }
1420 }
1421
1422
1423 /**
1424  * \brief Handle all pending DRQs.
1425  * \pre cpu_lock.test() (The CPU lock must be held).
1426  * \pre current() == this (only the currently running context is allowed to
1427  *      call this function).
1428  * \return true if re-scheduling is needed (ready queue has changed),
1429  *         false if not.
1430  */
1431 PUBLIC //inline
1432 bool
1433 Context::handle_drq()
1434 {
1435   assert_kdb (check_for_current_cpu());
1436   assert_kdb (cpu_lock.test());
1437
1438   try_finish_migration();
1439
1440   if (EXPECT_TRUE(!drq_pending()))
1441     return false;
1442
1443   Mem::barrier();
1444   bool ret = _drq_q.handle_requests();
1445   state_del_dirty(Thread_drq_ready);
1446
1447   //LOG_MSG_3VAL(this, "xdrq", state(), ret, cpu_lock.test());
1448
1449   /*
1450    * When the context is marked as dead (Thread_dead) then we must not execute
1451    * any usual context code, however DRQ handlers may run.
1452    */
1453   if (state() & Thread_dead)
1454     {
1455       // so disable the context after handling all DRQs and flag a reschedule.
1456       state_del_dirty(Thread_ready_mask);
1457       return true;
1458     }
1459
1460   return ret || !(state() & Thread_ready_mask);
1461 }
1462
1463
1464 /**
1465  * \brief Get the queue item of the context.
1466  * \pre The context must currently not be in any queue.
1467  * \return The queue item of the context.
1468  *
1469  * The queue item can be used to enqueue the context to a Queue.
1470  * a context must be in at most one queue at a time.
1471  * To figure out the context corresponding to a queue item
1472  * context_of() can be used.
1473  */
1474 PUBLIC inline NEEDS["kdb_ke.h"]
1475 Queue_item *
1476 Context::queue_item()
1477 {
1478   return &_drq;
1479 }
1480
1481 /**
1482  * \brief DRQ handler for state_change.
1483  *
1484  * This function basically wraps Context::state_change().
1485  */
1486 PRIVATE static
1487 unsigned
1488 Context::handle_drq_state_change(Drq * /*src*/, Context *self, void * _rq)
1489 {
1490   State_request *rq = reinterpret_cast<State_request*>(_rq);
1491   self->state_change_dirty(rq->del, rq->add);
1492   //LOG_MSG_3VAL(c, "dsta", c->state(), (Mword)src, (Mword)_rq);
1493   return false;
1494 }
1495
1496
1497 /**
1498  * \brief Queue a DRQ for changing the contexts state.
1499  * \param mask bit mask for the state (state &= mask).
1500  * \param add bits to add to the state (state |= add).
1501  * \note This function is a preemption point.
1502  *
1503  * This function must be used to change the state of contexts that are
1504  * potentially running on a different CPU.
1505  */
1506 PUBLIC inline NEEDS[Context::drq]
1507 void
1508 Context::drq_state_change(Mword mask, Mword add)
1509 {
1510   if (current() == this)
1511     {
1512       state_change_dirty(mask, add);
1513       return;
1514     }
1515
1516   State_request rq;
1517   rq.del = mask;
1518   rq.add = add;
1519   drq(handle_drq_state_change, &rq);
1520 }
1521
1522
1523 /**
1524  * \brief Initiate a DRQ for the context.
1525  * \pre \a src must be the currently running context.
1526  * \param src the source of the DRQ (the context who initiates the DRQ).
1527  * \param func the DRQ handler.
1528  * \param arg the argument for the DRQ handler.
1529  * \param reply the reply handler (called in the context of \a src immediately
1530  *        after receiving a successful reply).
1531  *
1532  * DRQs are requests that any context can queue to any other context. DRQs are
1533  * the basic mechanism to initiate actions on remote CPUs in an MP system,
1534  * however, are also allowed locally.
1535  * DRQ handlers of pending DRQs are executed by Context::handle_drq() in the
1536  * context of the target context. Context::handle_drq() is basically called
1537  * after switching to a context in Context::switch_exec_locked().
1538  *
1539  * This function enqueues a DRQ and blocks the current context for a reply DRQ.
1540  */
1541 PUBLIC inline NEEDS[Context::enqueue_drq, "logdefs.h"]
1542 void
1543 Context::drq(Drq *drq, Drq::Request_func *func, void *arg,
1544              Drq::Request_func *reply = 0,
1545              Drq::Exec_mode exec = Drq::Target_ctxt,
1546              Drq::Wait_mode wait = Drq::Wait)
1547 {
1548   // printf("CPU[%2u:%p]: > Context::drq(this=%p, src=%p, func=%p, arg=%p)\n", current_cpu(), current(), this, src, func,arg);
1549   Context *cur = current();
1550   LOG_TRACE("DRQ Stuff", "drq", cur, Drq_log,
1551       l->type = Drq_log::Type::Send;
1552       l->rq = drq;
1553       l->func = (void*)func;
1554       l->reply = (void*)reply;
1555       l->thread = this;
1556       l->target_cpu = cpu();
1557       l->wait = wait;
1558   );
1559   //assert_kdb (current() == src);
1560   assert_kdb (!(wait == Drq::Wait && (cur->state() & Thread_drq_ready)) || cur->cpu() == cpu());
1561   assert_kdb (!((wait == Drq::Wait || drq == &_drq) && cur->state() & Thread_drq_wait));
1562   assert_kdb (!drq->queued());
1563
1564   drq->func  = func;
1565   drq->reply = reply;
1566   drq->arg   = arg;
1567   cur->state_add(wait == Drq::Wait ? Thread_drq_wait : 0);
1568
1569
1570   enqueue_drq(drq, exec);
1571
1572   //LOG_MSG_3VAL(src, "<drq", src->state(), Mword(this), 0);
1573   while (wait == Drq::Wait && cur->state() & Thread_drq_wait)
1574     {
1575       cur->state_del(Thread_ready_mask);
1576       cur->schedule();
1577     }
1578
1579   LOG_TRACE("DRQ Stuff", "drq", cur, Drq_log,
1580       l->type = Drq_log::Type::Done;
1581       l->rq = drq;
1582       l->func = (void*)func;
1583       l->reply = (void*)reply;
1584       l->thread = this;
1585       l->target_cpu = cpu();
1586   );
1587   //LOG_MSG_3VAL(src, "drq>", src->state(), Mword(this), 0);
1588 }
1589
1590 PROTECTED inline
1591 void
1592 Context::kernel_context_drq(Drq::Request_func *func, void *arg,
1593                             Drq::Request_func *reply = 0)
1594 {
1595   char align_buffer[2*sizeof(Drq)];
1596   Drq *mdrq = new ((void*)((Address)(align_buffer + __alignof__(Drq) - 1) & ~(__alignof__(Drq)-1))) Drq;
1597
1598
1599   mdrq->func  = func;
1600   mdrq->arg   = arg;
1601   mdrq->reply = reply;
1602   Context *kc = kernel_context(current_cpu());
1603
1604   kc->_drq_q.enq(mdrq);
1605   bool resched = schedule_switch_to_locked(kc);
1606   (void)resched;
1607 }
1608
1609 PUBLIC inline NEEDS[Context::drq]
1610 void
1611 Context::drq(Drq::Request_func *func, void *arg,
1612              Drq::Request_func *reply = 0,
1613              Drq::Exec_mode exec = Drq::Target_ctxt,
1614              Drq::Wait_mode wait = Drq::Wait)
1615 { return drq(&current()->_drq, func, arg, reply, exec, wait); }
1616
1617 PRIVATE static
1618 bool
1619 Context::rcu_unblock(Rcu_item *i)
1620 {
1621   assert_kdb(cpu_lock.test());
1622   Context *const c = static_cast<Context*>(i);
1623   c->state_change_dirty(~Thread_waiting, Thread_ready);
1624   Sched_context::rq.current().deblock(c->sched());
1625   return true;
1626 }
1627
1628 PUBLIC inline
1629 void
1630 Context::recover_jmp_buf(jmp_buf *b)
1631 { _recover_jmpbuf = b; }
1632
1633 PUBLIC static
1634 void
1635 Context::xcpu_tlb_flush(...)
1636 {
1637   // This should always be optimized away
1638   assert(0);
1639 }
1640
1641 IMPLEMENT_DEFAULT inline
1642 void
1643 Context::arch_load_vcpu_kern_state(Vcpu_state *, bool)
1644 {}
1645
1646 IMPLEMENT_DEFAULT inline
1647 void
1648 Context::arch_load_vcpu_user_state(Vcpu_state *, bool)
1649 {}
1650
1651 IMPLEMENT_DEFAULT inline
1652 void
1653 Context::arch_update_vcpu_state(Vcpu_state *)
1654 {}
1655
1656 //----------------------------------------------------------------------------
1657 IMPLEMENTATION [!mp]:
1658
1659 #include "warn.h"
1660 #include "kdb_ke.h"
1661
1662 PUBLIC inline
1663 Cpu_number
1664 Context::cpu(bool running = false) const
1665 {
1666   if (running)
1667     return Cpu_number::boot_cpu();
1668
1669   return _cpu;
1670 }
1671
1672 PUBLIC static inline
1673 void
1674 Context::enable_tlb(Cpu_number)
1675 {}
1676
1677 PUBLIC static inline
1678 void
1679 Context::disable_tlb(Cpu_number)
1680 {}
1681
1682
1683 PROTECTED
1684 void
1685 Context::remote_ready_enqueue()
1686 {
1687   WARN("Context::remote_ready_enqueue(): in UP system !\n");
1688   kdb_ke("Fiasco BUG");
1689 }
1690
1691 PUBLIC
1692 bool
1693 Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/)
1694 {
1695   assert_kdb (cpu_lock.test());
1696
1697   if (access_once(&_cpu) != current_cpu())
1698     {
1699       bool do_sched = _drq_q.execute_request(rq, Drq_q::No_drop, true);
1700       //LOG_MSG_3VAL(this, "drqX", access_once(&_cpu), current_cpu(), state());
1701       if (access_once(&_cpu) == current_cpu() && (state() & Thread_ready_mask))
1702         {
1703           Sched_context::rq.current().ready_enqueue(sched());
1704           return true;
1705         }
1706       return do_sched;
1707     }
1708   else
1709     { // LOG_MSG_3VAL(this, "adrq", state(), (Mword)current(), (Mword)rq);
1710
1711       bool do_sched = _drq_q.execute_request(rq, Drq_q::No_drop, true);
1712       if (!in_ready_list() && (state() & Thread_ready_mask))
1713         {
1714           Sched_context::rq.current().ready_enqueue(sched());
1715           return true;
1716         }
1717
1718       return do_sched;
1719     }
1720   return false;
1721 }
1722
1723
1724 PRIVATE inline NOEXPORT
1725 void
1726 Context::shutdown_drqs()
1727 { _drq_q.handle_requests(Drq_q::Drop); }
1728
1729
1730 PUBLIC inline
1731 void
1732 Context::rcu_wait()
1733 {
1734   // The UP case does not need to block for the next grace period, because
1735   // the CPU is always in a quiescent state when the interrupts where enabled
1736 }
1737
1738 PUBLIC static inline
1739 void
1740 Context::xcpu_tlb_flush(bool, Mem_space *, Mem_space *)
1741 {}
1742
1743
1744
1745 //----------------------------------------------------------------------------
1746 INTERFACE [mp]:
1747
1748 #include "queue.h"
1749 #include "queue_item.h"
1750
1751 EXTENSION class Context
1752 {
1753 protected:
1754
1755   class Pending_rqq : public Queue
1756   {
1757   public:
1758     static void enq(Context *c);
1759     bool handle_requests(Context **);
1760   };
1761
1762   class Pending_rq : public Queue_item, public Context_member
1763   {} _pending_rq;
1764
1765 protected:
1766   static Per_cpu<Pending_rqq> _pending_rqq;
1767   static Per_cpu<Drq_q> _glbl_drq_q;
1768   static Cpu_mask _tlb_active;
1769
1770 };
1771
1772
1773
1774 //----------------------------------------------------------------------------
1775 IMPLEMENTATION [mp]:
1776
1777 #include "globals.h"
1778 #include "ipi.h"
1779 #include "kdb_ke.h"
1780 #include "lock_guard.h"
1781 #include "mem.h"
1782
1783 DEFINE_PER_CPU Per_cpu<Context::Pending_rqq> Context::_pending_rqq;
1784 DEFINE_PER_CPU Per_cpu<Context::Drq_q> Context::_glbl_drq_q;
1785 Cpu_mask Context::_tlb_active;
1786
1787 PUBLIC static inline
1788 void
1789 Context::enable_tlb(Cpu_number cpu)
1790 { _tlb_active.atomic_set(cpu); }
1791
1792 PUBLIC static inline
1793 void
1794 Context::disable_tlb(Cpu_number cpu)
1795 { _tlb_active.atomic_clear(cpu); }
1796
1797 /**
1798  * \brief Enqueue the given \a c into its CPUs queue.
1799  * \param c the context to enqueue for DRQ handling.
1800  */
1801 IMPLEMENT inline NEEDS["globals.h", "lock_guard.h", "kdb_ke.h"]
1802 void
1803 Context::Pending_rqq::enq(Context *c)
1804 {
1805   // FIXME: is it safe to do the check without a locked queue, or may
1806   //        we loose DRQs then?
1807
1808   //if (!c->_pending_rq.queued())
1809     {
1810       Queue &q = Context::_pending_rqq.cpu(c->cpu());
1811       auto guard = lock_guard(q.q_lock());
1812       if (c->_pending_rq.queued())
1813         return;
1814       q.enqueue(&c->_pending_rq);
1815     }
1816 }
1817
1818
1819 /**
1820  * \brief Wakeup all contexts with pending DRQs.
1821  *
1822  * This function wakes up all context from the pending queue.
1823  */
1824 IMPLEMENT
1825 bool
1826 Context::Pending_rqq::handle_requests(Context **mq)
1827 {
1828   //LOG_MSG_3VAL(current(), "phq", current_cpu(), 0, 0);
1829   // printf("CPU[%2u:%p]: Context::Pending_rqq::handle_requests() this=%p\n", current_cpu(), current(), this);
1830   bool resched = false;
1831   Context *curr = current();
1832   while (1)
1833     {
1834       Context *c;
1835         {
1836           auto guard = lock_guard(q_lock());
1837           Queue_item *qi = first();
1838           if (!qi)
1839             return resched;
1840
1841           check_kdb (dequeue(qi, Queue_item::Ok));
1842           c = static_cast<Context::Pending_rq *>(qi)->context();
1843         }
1844
1845       assert_kdb (c->check_for_current_cpu());
1846
1847       if (EXPECT_FALSE(c->_migration != 0))
1848         {
1849           // if the currently executing thread shall be migrated we must defer
1850           // this until we have handled the whole request queue, otherwise we
1851           // would miss the remaining requests or execute them on the wrong CPU.
1852           if (c != curr)
1853             {
1854               // we can directly migrate the thread...
1855               resched |= c->initiate_migration();
1856
1857               // if migrated away skip the resched test below
1858               if (access_once(&c->_cpu) != current_cpu())
1859                 continue;
1860             }
1861           else
1862             *mq = c;
1863         }
1864       else
1865         c->try_finish_migration();
1866
1867       if (EXPECT_TRUE(c != curr && c->drq_pending()))
1868         c->state_add(Thread_drq_ready);
1869
1870       // FIXME: must we also reschedule when c cannot preempt the current
1871       // thread but its current scheduling context?
1872       if (EXPECT_TRUE(c != curr && (c->state() & Thread_ready_mask)))
1873         {
1874           //printf("CPU[%2u:%p]:   Context::Pending_rqq::handle_requests() dequeded %p(%u)\n", current_cpu(), current(), c, qi->queued());
1875           resched |= Sched_context::rq.current().deblock(c->sched(), curr->sched(), false);
1876         }
1877     }
1878 }
1879
1880 PUBLIC
1881 void
1882 Context::global_drq(Cpu_number cpu, Drq::Request_func *func, void *arg,
1883                     Drq::Request_func *reply = 0, bool wait = true)
1884 {
1885   assert_kdb (this == current());
1886
1887   _drq.func  = func;
1888   _drq.reply = reply;
1889   _drq.arg   = arg;
1890
1891   state_add(wait ? Thread_drq_wait : 0);
1892
1893   _glbl_drq_q.cpu(cpu).enq(&_drq);
1894
1895   Ipi::send(Ipi::Global_request, this->cpu(), cpu);
1896
1897   //LOG_MSG_3VAL(this, "<drq", state(), Mword(this), 0);
1898   while (wait && (state() & Thread_drq_wait))
1899     {
1900       state_del(Thread_ready_mask);
1901       schedule();
1902     }
1903 }
1904
1905
1906 PUBLIC
1907 static bool
1908 Context::handle_global_requests()
1909 {
1910   return _glbl_drq_q.cpu(current_cpu()).handle_requests();
1911 }
1912
1913 PUBLIC
1914 bool
1915 Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/)
1916 {
1917   assert_kdb (cpu_lock.test());
1918   // printf("CPU[%2u:%p]: Context::enqueue_request(this=%p, src=%p, func=%p, arg=%p)\n", current_cpu(), current(), this, src, func,arg);
1919
1920   if (cpu() != current_cpu())
1921     {
1922       bool ipi = false;
1923       _drq_q.enq(rq);
1924
1925       // read cpu again we may've been migrated meanwhile
1926       Cpu_number cpu = access_once(&this->_cpu);
1927
1928         {
1929           Queue &q = Context::_pending_rqq.cpu(cpu);
1930           auto guard = lock_guard(q.q_lock());
1931
1932
1933           // migrated between getting the lock and reading the CPU, so the
1934           // new CPU is responsible for executing our request
1935           if (access_once(&this->_cpu) != cpu)
1936             return false;
1937
1938           if (EXPECT_FALSE(!Cpu::online(cpu)))
1939             {
1940               if (EXPECT_FALSE(!_drq_q.dequeue(rq, Queue_item::Ok)))
1941                 // handled already
1942                 return false;
1943
1944               // execute locally under the target CPU's queue lock
1945               _drq_q.execute_request(rq, Drq_q::No_drop, true);
1946
1947               // free the lock early
1948               guard.reset();
1949               if (   access_once(&this->_cpu) == current_cpu()
1950                   && !in_ready_list()
1951                   && (state() & Thread_ready_mask))
1952                 {
1953                   Sched_context::rq.current().ready_enqueue(sched());
1954                   return true;
1955                 }
1956               return false;
1957             }
1958
1959           if (!_pending_rq.queued())
1960             {
1961               if (!q.first())
1962                 ipi = true;
1963
1964               q.enqueue(&_pending_rq);
1965             }
1966         }
1967
1968       if (ipi)
1969         {
1970           //LOG_MSG_3VAL(this, "sipi", current_cpu(), cpu(), (Mword)current());
1971           Ipi::send(Ipi::Request, current_cpu(), cpu);
1972         }
1973     }
1974   else
1975     { // LOG_MSG_3VAL(this, "adrq", state(), (Mword)current(), (Mword)rq);
1976
1977       bool do_sched = _drq_q.execute_request(rq, Drq_q::No_drop, true);
1978       if (!in_ready_list() && (state() & Thread_ready_mask))
1979         {
1980           Sched_context::rq.current().ready_enqueue(sched());
1981           return true;
1982         }
1983
1984       return do_sched;
1985     }
1986   return false;
1987 }
1988
1989
1990 PRIVATE inline NOEXPORT
1991 void
1992 Context::shutdown_drqs()
1993 {
1994   if (_pending_rq.queued())
1995     {
1996       auto guard = lock_guard(_pending_rq.queue()->q_lock());
1997       if (_pending_rq.queued())
1998         _pending_rq.queue()->dequeue(&_pending_rq, Queue_item::Ok);
1999     }
2000
2001   _drq_q.handle_requests(Drq_q::Drop);
2002 }
2003
2004
2005 PUBLIC inline
2006 Cpu_number
2007 Context::cpu(bool running = false) const
2008 {
2009   (void)running;
2010   return _cpu;
2011 }
2012
2013
2014 /**
2015  * Remote helper for doing remote CPU ready enqueue.
2016  *
2017  * See remote_ready_enqueue().
2018  */
2019 PRIVATE static
2020 unsigned
2021 Context::handle_remote_ready_enqueue(Drq *, Context *self, void *)
2022 {
2023   self->state_add_dirty(Thread_ready);
2024   return 0;
2025 }
2026
2027
2028 PROTECTED inline NEEDS[Context::handle_remote_ready_enqueue]
2029 void
2030 Context::remote_ready_enqueue()
2031 { drq(&handle_remote_ready_enqueue, 0); }
2032
2033
2034
2035 /**
2036  * Block and wait for the next grace period.
2037  */
2038 PUBLIC inline NEEDS["cpu_lock.h", "lock_guard.h"]
2039 void
2040 Context::rcu_wait()
2041 {
2042   auto gurad = lock_guard(cpu_lock);
2043   state_change_dirty(~Thread_ready, Thread_waiting);
2044   Rcu::call(this, &rcu_unblock);
2045   schedule();
2046 }
2047
2048
2049
2050 PRIVATE static
2051 unsigned
2052 Context::handle_remote_tlb_flush(Drq *, Context *, void *_s)
2053 {
2054   Mem_space **s = (Mem_space **)_s;
2055   Mem_space::tlb_flush_spaces((bool)s[0], s[1], s[2]);
2056
2057   return 0;
2058 }
2059
2060
2061 PUBLIC static
2062 void
2063 Context::xcpu_tlb_flush(bool flush_all_spaces, Mem_space *s1, Mem_space *s2)
2064 {
2065   auto g = lock_guard(cpu_lock);
2066   Mem_space *s[3] = { (Mem_space *)flush_all_spaces, s1, s2 };
2067   Cpu_number ccpu = current_cpu();
2068   for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
2069     if (ccpu != i && _tlb_active.get(i))
2070       current()->global_drq(i, Context::handle_remote_tlb_flush, s);
2071 }
2072
2073 //----------------------------------------------------------------------------
2074 IMPLEMENTATION [fpu && !ux]:
2075
2076 #include "fpu.h"
2077
2078 PUBLIC inline NEEDS ["fpu.h"]
2079 void
2080 Context::spill_fpu()
2081 {
2082   // If we own the FPU, we should never be getting an "FPU unavailable" trap
2083   assert_kdb (Fpu::fpu.current().owner() == this);
2084   assert_kdb (state() & Thread_fpu_owner);
2085   assert_kdb (fpu_state());
2086
2087   // Save the FPU state of the previous FPU owner (lazy) if applicable
2088   Fpu::save_state(fpu_state());
2089   state_del_dirty(Thread_fpu_owner);
2090 }
2091
2092
2093 /**
2094  * When switching away from the FPU owner, disable the FPU to cause
2095  * the next FPU access to trap.
2096  * When switching back to the FPU owner, enable the FPU so we don't
2097  * get an FPU trap on FPU access.
2098  */
2099 IMPLEMENT inline NEEDS ["fpu.h"]
2100 void
2101 Context::switch_fpu(Context *t)
2102 {
2103   Fpu &f = Fpu::fpu.current();
2104   if (f.is_owner(this))
2105     f.disable();
2106   else if (f.is_owner(t) && !(t->state() & Thread_vcpu_fpu_disabled))
2107     f.enable();
2108 }
2109
2110 //----------------------------------------------------------------------------
2111 IMPLEMENTATION [!fpu]:
2112
2113 PUBLIC inline
2114 void
2115 Context::spill_fpu()
2116 {}
2117
2118 IMPLEMENT inline
2119 void
2120 Context::switch_fpu(Context *)
2121 {}
2122
2123 //----------------------------------------------------------------------------
2124 INTERFACE [debug]:
2125
2126 #include "tb_entry.h"
2127
2128 /** logged context switch. */
2129 class Tb_entry_ctx_sw : public Tb_entry
2130 {
2131 public:
2132   using Tb_entry::_ip;
2133
2134   Context const *dst;           ///< switcher target
2135   Context const *dst_orig;
2136   Address kernel_ip;
2137   Mword lock_cnt;
2138   Space const *from_space;
2139   Sched_context const *from_sched;
2140   Mword from_prio;
2141   unsigned print(int max, char *buf) const;
2142 } __attribute__((packed));
2143
2144
2145
2146 // --------------------------------------------------------------------------
2147 IMPLEMENTATION [debug]:
2148
2149 #include "kobject_dbg.h"
2150
2151 IMPLEMENT
2152 unsigned
2153 Context::Drq_log::print(int maxlen, char *buf) const
2154 {
2155   static char const *const _types[] =
2156     { "send", "request", "reply", "done" };
2157
2158   char const *t = "unk";
2159   if ((unsigned)type < sizeof(_types)/sizeof(_types[0]))
2160     t = _types[(unsigned)type];
2161
2162   return snprintf(buf, maxlen, "%s(%s) rq=%p to ctxt=%lx/%p (func=%p, reply=%p) cpu=%u",
2163       t, wait ? "wait" : "no-wait", rq, Kobject_dbg::pointer_to_id(thread),
2164       thread, func, reply, cxx::int_value<Cpu_number>(target_cpu));
2165 }
2166
2167 // context switch
2168 IMPLEMENT
2169 unsigned
2170 Tb_entry_ctx_sw::print(int maxlen, char *buf) const
2171 {
2172   char symstr[24];
2173   int max = maxlen;
2174
2175   Context *sctx = 0;
2176   Mword sctxid = ~0UL;
2177   Mword dst;
2178   Mword dst_orig;
2179
2180   sctx = from_sched->context();
2181   sctxid = Kobject_dbg::pointer_to_id(sctx);
2182
2183   dst = Kobject_dbg::pointer_to_id(this->dst);
2184   dst_orig = Kobject_dbg::pointer_to_id(this->dst_orig);
2185
2186   snprintf(symstr, sizeof(symstr), L4_PTR_FMT, kernel_ip); // Jdb_symbol::...
2187
2188   if (sctx != ctx())
2189     maxlen -= snprintf(buf, maxlen, "(%lx)", sctxid);
2190
2191   maxlen -= snprintf(buf, maxlen, " ==> %lx ", dst);
2192
2193   if (dst != dst_orig || lock_cnt)
2194     maxlen -= snprintf(buf, maxlen, "(");
2195
2196   if (dst != dst_orig)
2197     maxlen -= snprintf(buf, maxlen, "want %lx", dst_orig);
2198
2199   if (dst != dst_orig && lock_cnt)
2200     maxlen -= snprintf(buf, maxlen, " ");
2201
2202   if (lock_cnt)
2203     maxlen -= snprintf(buf, maxlen, "lck %ld", lock_cnt);
2204
2205   if (dst != dst_orig || lock_cnt)
2206     maxlen -= snprintf(buf, maxlen, ") ");
2207
2208   maxlen -= snprintf(buf, maxlen, " krnl %s", symstr);
2209
2210   return max - maxlen;
2211 }
2212
2213