]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/sched_context.cpp
87b651ef8113ce6d83ae92e7b1b66e184b66244c
[l4.git] / kernel / fiasco / src / kern / sched_context.cpp
1 INTERFACE:
2 #include "per_cpu_data.h"
3
4 EXTENSION class Sched_context
5 {
6 public:
7   class Ready_queue : public Ready_queue_base
8   {
9   public:
10     void set_current_sched(Sched_context *sched);
11     void invalidate_sched() { activate(0); }
12     bool deblock(Sched_context *sc, Sched_context *crs, bool lazy_q = false);
13     void deblock(Sched_context *sc);
14     void ready_enqueue(Sched_context *sc)
15     {
16       assert_kdb(cpu_lock.test());
17
18       // Don't enqueue threads which are already enqueued
19       if (EXPECT_FALSE (sc->in_ready_list()))
20         return;
21
22       enqueue(sc, sc == current_sched());
23     }
24
25     void ready_dequeue(Sched_context *sc)
26     {
27       assert_kdb (cpu_lock.test());
28
29       // Don't dequeue threads which aren't enqueued
30       if (EXPECT_FALSE (!sc->in_ready_list()))
31         return;
32
33       dequeue(sc);
34     }
35
36     void switch_sched(Sched_context *from, Sched_context *to)
37     {
38       assert_kdb (cpu_lock.test());
39
40       // If we're leaving the global timeslice, invalidate it This causes
41       // schedule() to select a new timeslice via set_current_sched()
42       if (from == current_sched())
43         invalidate_sched();
44
45       if (from->in_ready_list())
46         dequeue(from);
47
48       enqueue(to, false);
49     }
50
51     Context *schedule_in_progress;
52   };
53
54   static Per_cpu<Ready_queue> rq;
55 };
56
57 IMPLEMENTATION:
58
59 #include "kdb_ke.h"
60 #include "timer.h"
61 #include "timeout.h"
62 #include "globals.h"
63 #include "logdefs.h"
64
65 DEFINE_PER_CPU Per_cpu<Sched_context::Ready_queue> Sched_context::rq;
66
67 /**
68  * Set currently active global Sched_context.
69  */
70 IMPLEMENT
71 void
72 Sched_context::Ready_queue::set_current_sched(Sched_context *sched)
73 {
74   assert_kdb (sched);
75   // Save remainder of previous timeslice or refresh it, unless it had
76   // been invalidated
77   Timeout * const tt = timeslice_timeout.current();
78   Unsigned64 clock = Timer::system_clock();
79   if (Sched_context *s = current_sched())
80     {
81       Signed64 left = tt->get_timeout(clock);
82       if (left > 0)
83         s->set_left(left);
84       else
85         s->replenish();
86
87       LOG_SCHED_SAVE(s);
88     }
89
90   // Program new end-of-timeslice timeout
91   tt->reset();
92   tt->set(clock + sched->left(), current_cpu());
93
94   // Make this timeslice current
95   activate(sched);
96
97   LOG_SCHED_LOAD(sched);
98 }
99
100
101 /**
102  * \param cpu must be current_cpu()
103  */
104 IMPLEMENT inline NEEDS["kdb_ke.h"]
105 void
106 Sched_context::Ready_queue::deblock(Sched_context *sc)
107 {
108   assert_kdb(cpu_lock.test());
109
110   Sched_context *cs = current_sched();
111   if (sc != cs)
112       deblock_refill(sc);
113
114   ready_enqueue(sc);
115 }
116
117 /**
118  * \param cpu must be current_cpu()
119  * \param crs the Sched_context of the current context
120  * \param lazy_q queue lazily if applicable
121  */
122 IMPLEMENT inline NEEDS["kdb_ke.h"]
123 bool
124 Sched_context::Ready_queue::deblock(Sched_context *sc, Sched_context *crs, bool lazy_q)
125 {
126   assert_kdb(cpu_lock.test());
127
128   Sched_context *cs = current_sched();
129   bool res = true;
130   if (sc == cs)
131     {
132       if (crs->dominates(sc))
133         res = false;
134     }
135   else
136     {
137       deblock_refill(sc);
138
139       if ((EXPECT_TRUE(cs != 0) && cs->dominates(sc)) || crs->dominates(sc))
140         res = false;
141     }
142
143   if (res && lazy_q)
144     return true;
145
146   ready_enqueue(sc);
147   return res;
148 }
149