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