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