SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /sos/sched.c (Article 7.5) and /sos/sched.c (Article 6.5)


001 /* Copyright (C) 2004 David Decotigny             001 /* Copyright (C) 2004 David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <sos/errno.h>                            019 #include <sos/errno.h>
020 #include <sos/klibc.h>                            020 #include <sos/klibc.h>
021 #include <sos/assert.h>                           021 #include <sos/assert.h>
022 #include <sos/list.h>                             022 #include <sos/list.h>
023 #include <sos/calcload.h>                      << 
024                                                   023 
025 #include "sched.h"                                024 #include "sched.h"
026                                                   025 
027                                                   026 
028 /**                                               027 /**
029  * The definition of the scheduler queue. We c    028  * The definition of the scheduler queue. We could have used a normal
030  * kwaitq here, it would have had the same pro !! 029  * kwaitq here, it would have had the same properties. But, in the
031  * priority ordering mainly). But we don't bot !! 030  * definitive version (O(1) scheduler), the structure has to be a bit
032  * considerations here (in kwaitq, we had bett !! 031  * more complicated. So, in order to keep the changes as small as
033  * structure as small as possible because ther !! 032  * possible between this version and the definitive one, we don't use
034  * the system: at least 1 per opened file), so !! 033  * kwaitq here.
035  * much faster way of handling the prioritized << 
036  */                                               034  */
037 struct sos_sched_queue                         !! 035 static struct
038 {                                                 036 {
039   unsigned int nr_threads;                        037   unsigned int nr_threads;
040   struct sos_thread *thread_list[SOS_SCHED_NUM !! 038   struct sos_thread *thread_list;
041 };                                             !! 039 } ready_queue;
042                                                << 
043                                                << 
044 /**                                            << 
045  * We manage 2 queues: a queue being scanned f << 
046  * (active_queue) and a queue to store the thr << 
047  * expired their time quantuum.                << 
048  */                                            << 
049 static struct sos_sched_queue *active_queue, * << 
050                                                << 
051                                                << 
052 /**                                            << 
053  * The instances for the active/expired queues << 
054  */                                            << 
055 static struct sos_sched_queue sched_queue[2];  << 
056                                                << 
057                                                << 
058 /**                                            << 
059  * The array giving the timeslice correspondin << 
060  */                                            << 
061 struct sos_time time_slice[SOS_SCHED_NUM_PRIO] << 
062                                                   040 
063                                                   041 
064 sos_ret_t sos_sched_subsystem_setup()             042 sos_ret_t sos_sched_subsystem_setup()
065 {                                                 043 {
066   sos_sched_priority_t prio;                   !! 044   memset(& ready_queue, 0x0, sizeof(ready_queue));
067                                                << 
068   memset(sched_queue, 0x0, sizeof(sched_queue) << 
069   active_queue  = & sched_queue[0];            << 
070   expired_queue = & sched_queue[1];            << 
071                                                << 
072   /* pre-compute time slices */                << 
073   for (prio = SOS_SCHED_PRIO_TS_HIGHEST ;      << 
074        prio <= SOS_SCHED_PRIO_TS_LOWEST ;      << 
075        prio ++)                                << 
076     {                                          << 
077       unsigned int ms;                         << 
078       ms = SOS_TIME_SLICE_MIN                  << 
079            + (SOS_TIME_SLICE_MAX - SOS_TIME_SL << 
080              * (prio - SOS_SCHED_PRIO_TS_HIGHE << 
081              / (SOS_SCHED_PRIO_TS_LOWEST - SOS << 
082       time_slice[prio].sec     = ms / 1000;    << 
083       time_slice[prio].nanosec = 1000000UL * ( << 
084     }                                          << 
085                                                   045 
086   return SOS_OK;                                  046   return SOS_OK;
087 }                                                 047 }
088                                                   048 
089                                                   049 
090 /**                                               050 /**
091  * Helper function to add a thread in a ready     051  * Helper function to add a thread in a ready queue AND to change the
092  * state of the given thread to "READY".          052  * state of the given thread to "READY".
093  *                                                053  *
094  * @param insert_at_tail TRUE to tell to add t    054  * @param insert_at_tail TRUE to tell to add the thread at the end of
095  * the ready list. Otherwise it is added at th    055  * the ready list. Otherwise it is added at the head of it.
096  */                                               056  */
097 static sos_ret_t add_in_ready_queue(struct sos !! 057 static sos_ret_t add_in_ready_queue(struct sos_thread *thr,
098                                     struct sos << 
099                                     sos_bool_t    058                                     sos_bool_t insert_at_tail)
100 {                                                 059 {
101   sos_sched_priority_t prio;                   << 
102                                                   060 
103   SOS_ASSERT_FATAL( (SOS_THR_CREATED == thr->s    061   SOS_ASSERT_FATAL( (SOS_THR_CREATED == thr->state)
104                     || (SOS_THR_RUNNING == thr    062                     || (SOS_THR_RUNNING == thr->state) /* Yield */
105                     || (SOS_THR_BLOCKED == thr    063                     || (SOS_THR_BLOCKED == thr->state) );
106                                                   064 
107   /* Add the thread to the CPU queue */           065   /* Add the thread to the CPU queue */
108   prio = sos_thread_get_priority(thr);         << 
109   if (insert_at_tail)                             066   if (insert_at_tail)
110     list_add_tail_named(q->thread_list[prio],  !! 067     list_add_tail_named(ready_queue.thread_list, thr,
111                         ready.rdy_prev, ready.    068                         ready.rdy_prev, ready.rdy_next);
112   else                                            069   else
113     list_add_head_named(q->thread_list[prio],  !! 070     list_add_head_named(ready_queue.thread_list, thr,
114                         ready.rdy_prev, ready.    071                         ready.rdy_prev, ready.rdy_next);
115   thr->ready.rdy_queue = q;                    !! 072   ready_queue.nr_threads ++;
116   q->nr_threads ++;                            << 
117                                                   073 
118   /* Ok, thread is now really ready to be (re)    074   /* Ok, thread is now really ready to be (re)started */
119   thr->state = SOS_THR_READY;                     075   thr->state = SOS_THR_READY;
120                                                   076 
121   return SOS_OK;                                  077   return SOS_OK;
122 }                                                 078 }
123                                                   079 
124                                                   080 
125 sos_ret_t sos_sched_set_ready(struct sos_threa    081 sos_ret_t sos_sched_set_ready(struct sos_thread *thr)
126 {                                                 082 {
127   sos_ret_t retval;                               083   sos_ret_t retval;
128                                                   084 
129   /* Don't do anything for already ready threa    085   /* Don't do anything for already ready threads */
130   if (SOS_THR_READY == thr->state)                086   if (SOS_THR_READY == thr->state)
131     return SOS_OK;                                087     return SOS_OK;
132                                                   088 
133   /* Reset the CPU time used in the quantuum * !! 089   /* Real-time thread: schedule it for the present turn */
134   memset(& thr->running.user_time_spent_in_sli !! 090   retval = add_in_ready_queue(thr, TRUE);
135                                                << 
136   if (SOS_SCHED_PRIO_IS_RT(sos_thread_get_prio << 
137     {                                          << 
138       /* Real-time thread: schedule it for the << 
139       retval = add_in_ready_queue(active_queue << 
140     }                                          << 
141   else                                         << 
142     {                                          << 
143       /* Non real-time thread: schedule it for << 
144       retval = add_in_ready_queue(expired_queu << 
145     }                                          << 
146                                                   091 
147   return retval;                                  092   return retval;
148 }                                                 093 }
149                                                   094 
150                                                   095 
151 sos_ret_t sos_sched_change_priority(struct sos << 
152                                     sos_sched_ << 
153 {                                              << 
154   struct sos_thread *thread_list;              << 
155   SOS_ASSERT_FATAL(SOS_THR_READY == thr->state << 
156                                                << 
157   /* Temp variable */                          << 
158   thread_list                                  << 
159     = thr->ready.rdy_queue->thread_list[sos_th << 
160                                                << 
161   list_delete_named(thread_list, thr, ready.rd << 
162                                                << 
163   /* Update lists */                           << 
164   thread_list = thr->ready.rdy_queue->thread_l << 
165   list_add_tail_named(thread_list, thr, ready. << 
166   thr->ready.rdy_queue->thread_list[priority]  << 
167                                                << 
168   return SOS_OK;                               << 
169 }                                              << 
170                                                << 
171                                                << 
172 /**                                            << 
173  * Helper function to determine whether the cu << 
174  * time quantuum                               << 
175  */                                            << 
176 static sos_bool_t                              << 
177 thread_expired_its_quantuum(struct sos_thread  << 
178 {                                              << 
179   sos_sched_priority_t prio = sos_thread_get_p << 
180                                                << 
181   /* No timesharing/round-robin for "real-time << 
182   if (SOS_SCHED_PRIO_IS_RT(prio))              << 
183     return FALSE;                              << 
184                                                << 
185   /* Current (user) thread expired its time qu << 
186      thread never expires because sos_sched_do << 
187      won't update its user_time_spent_in_slice << 
188   if (sos_time_cmp(& thr->running.user_time_sp << 
189                    & time_slice[prio]) >= 0)   << 
190       return TRUE;                             << 
191                                                << 
192   return FALSE;                                << 
193 }                                              << 
194                                                << 
195                                                << 
196 struct sos_thread * sos_reschedule(struct sos_    096 struct sos_thread * sos_reschedule(struct sos_thread *current_thread,
197                                    sos_bool_t     097                                    sos_bool_t do_yield)
198 {                                                 098 {
199   sos_sched_priority_t prio;                   << 
200                                                << 
201   /* Force the current thread to release the C << 
202      quantuum */                               << 
203   if (thread_expired_its_quantuum(current_thre << 
204     {                                          << 
205       /* Reset the CPU time used in the quantu << 
206       memset(& current_thread->running.user_ti << 
207              0x0, sizeof(struct sos_time));    << 
208                                                << 
209       do_yield = TRUE;                         << 
210     }                                          << 
211                                                   099 
212   if (SOS_THR_ZOMBIE == current_thread->state)    100   if (SOS_THR_ZOMBIE == current_thread->state)
213     {                                             101     {
214       /* Don't think of returning to this thre    102       /* Don't think of returning to this thread since it is
215          terminated */                            103          terminated */
216       /* Nop */                                   104       /* Nop */
217     }                                             105     }
218   else if (SOS_THR_BLOCKED != current_thread->    106   else if (SOS_THR_BLOCKED != current_thread->state)
219     {                                             107     {
220       /* Take into account the current executi    108       /* Take into account the current executing thread unless it is
221          marked blocked */                        109          marked blocked */
222       if (do_yield)                               110       if (do_yield)
223         {                                      !! 111         /* Ok, reserve it for next turn */
224           /* Ok, reserve it for next turn */   !! 112         add_in_ready_queue(current_thread, TRUE);
225           if (SOS_SCHED_PRIO_IS_RT(sos_thread_ << 
226             add_in_ready_queue(active_queue, c << 
227           else                                 << 
228             add_in_ready_queue(expired_queue,  << 
229         }                                      << 
230       else                                        113       else
231         {                                      !! 114         /* Put it at the head of the active list */
232           /* Put it at the head of the active  !! 115         add_in_ready_queue(current_thread, FALSE);
233           add_in_ready_queue(active_queue, cur << 
234         }                                      << 
235     }                                             116     }
236                                                   117 
237                                                !! 118   /* The next thread is that at the head of the ready list */
238   /* Active queue is empty ? */                !! 119   if (ready_queue.nr_threads > 0)
239   if (active_queue->nr_threads <= 0)           << 
240     {                                          << 
241       /* Yes: Exchange it with the expired que << 
242       struct sos_sched_queue *q;               << 
243       q = active_queue;                        << 
244       active_queue = expired_queue;            << 
245       expired_queue = q;                       << 
246     }                                          << 
247                                                << 
248   /* Now loop over the priorities in the activ << 
249      non-empty queue */                        << 
250   for (prio = SOS_SCHED_PRIO_HIGHEST ; prio <= << 
251     {                                             120     {
252       struct sos_thread *next_thr;                121       struct sos_thread *next_thr;
253                                                   122 
254       if (list_is_empty_named(active_queue->th << 
255                               ready.rdy_prev,  << 
256         continue;                              << 
257                                                << 
258       /* Queue is not empty: take the thread a    123       /* Queue is not empty: take the thread at its head */
259       next_thr = list_pop_head_named(active_qu !! 124       next_thr = list_pop_head_named(ready_queue.thread_list,
260                                      ready.rdy    125                                      ready.rdy_prev, ready.rdy_next);
261       active_queue->nr_threads --;             !! 126       ready_queue.nr_threads --;
262                                                   127 
263       return next_thr;                            128       return next_thr;
264     }                                             129     }
265                                                   130 
266                                                << 
267   SOS_FATAL_ERROR("No kernel thread ready ?!")    131   SOS_FATAL_ERROR("No kernel thread ready ?!");
268   return NULL;                                    132   return NULL;
269 }                                              << 
270                                                << 
271                                                << 
272 sos_ret_t sos_sched_do_timer_tick()            << 
273 {                                              << 
274   struct sos_thread *interrupted_thread = sos_ << 
275   struct sos_time tick_duration;               << 
276   sos_bool_t cur_is_user;                      << 
277   sos_ui32_t nb_user_ready = 0;                << 
278   sos_ui32_t nb_kernel_ready = 0;              << 
279   int prio;                                    << 
280                                                << 
281   sos_time_get_tick_resolution(& tick_duration << 
282                                                << 
283   /* Update the timing statistics */           << 
284   if (sos_cpu_context_is_in_user_mode(interrup << 
285     {                                          << 
286       cur_is_user = TRUE;                      << 
287                                                << 
288       /* User time */                          << 
289       sos_time_inc(& interrupted_thread->rusag << 
290                    & tick_duration);           << 
291                                                << 
292       /* Update time spent is current timeslic << 
293       sos_time_inc(& interrupted_thread->runni << 
294                    & tick_duration);           << 
295     }                                          << 
296   else                                         << 
297     {                                          << 
298       cur_is_user = FALSE;                     << 
299                                                << 
300       /* System time */                        << 
301       sos_time_inc(& interrupted_thread->rusag << 
302                    & tick_duration);           << 
303     }                                          << 
304                                                << 
305                                                << 
306   /* Update load stats */                      << 
307   for (prio = SOS_SCHED_PRIO_HIGHEST ; prio <= << 
308     {                                          << 
309       struct sos_thread *thr;                  << 
310       int nb_thrs;                             << 
311                                                << 
312       list_foreach_forward_named(active_queue- << 
313                                  thr, nb_thrs, << 
314                                  ready.rdy_pre << 
315         {                                      << 
316           if (sos_cpu_context_is_in_user_mode( << 
317             nb_user_ready ++;                  << 
318           else                                 << 
319             nb_kernel_ready ++;                << 
320         }                                      << 
321                                                << 
322       list_foreach_forward_named(expired_queue << 
323                                  thr, nb_thrs, << 
324                                  ready.rdy_pre << 
325         {                                      << 
326           if (sos_cpu_context_is_in_user_mode( << 
327             nb_user_ready ++;                  << 
328           else                                 << 
329             nb_kernel_ready ++;                << 
330         }                                      << 
331     }                                          << 
332                                                << 
333   sos_load_do_timer_tick(cur_is_user,          << 
334                          nb_user_ready,        << 
335                          nb_kernel_ready);     << 
336                                                << 
337   return SOS_OK;                               << 
338 }                                                 133 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]