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