Subversion Repositories HelenOS-doc

Rev

Rev 131 | Rev 140 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 131 Rev 133
Line 77... Line 77...
77
 
77
 
78
      <para>The scheduler, but also other pieces of the kernel, make heavy use
78
      <para>The scheduler, but also other pieces of the kernel, make heavy use
79
      of synchronous context switches, because it is a natural vehicle not
79
      of synchronous context switches, because it is a natural vehicle not
80
      only for changes in control flow, but also for switching between two
80
      only for changes in control flow, but also for switching between two
81
      kernel stacks. Two functions figure in a synchronous context switch
81
      kernel stacks. Two functions figure in a synchronous context switch
82
      implementation: <code>context_save</code> and
82
      implementation: <code>context_save()</code> and
83
      <code>context_restore</code>. Note that these two functions break the
83
      <code>context_restore()</code>. Note that these two functions break the
84
      natural perception of the linear C code execution flow starting at
84
      natural perception of the linear C code execution flow starting at
85
      function's entry point and ending on one of the function's exit
85
      function's entry point and ending on one of the function's exit
86
      points.</para>
86
      points.</para>
87
 
87
 
88
      <para>When the <code>context_save</code> function is called, the
88
      <para>When the <code>context_save()</code> function is called, the
89
      synchronous context is saved in a memory structure passed to it. After
89
      synchronous context is saved in a memory structure passed to it. After
90
      executing <code>context_save</code>, the caller is returned 1 as a
90
      executing <code>context_save()</code>, the caller is returned 1 as a
91
      return value. The execution of instructions continues as normally until
91
      return value. The execution of instructions continues as normally until
92
      <code>context_restore</code> is called. For the caller, it seems like
92
      <code>context_restore()</code> is called. For the caller, it seems like
93
      the call never returns<footnote>
93
      the call never returns<footnote>
94
          <para>Which might be a source of problems with variable liveliness
94
          <para>Which might be a source of problems with variable liveliness
95
          after <code>context_restore</code>.</para>
95
          after <code>context_restore()</code>.</para>
96
        </footnote>. Nevertheless, a synchronous register context, which is
96
        </footnote>. Nevertheless, a synchronous register context, which is
97
      saved in a memory structure passed to <code>context_restore,</code> is
97
      saved in a memory structure passed to <code>context_restore()</code>, is
98
      restored, thus transfering the control flow to the place of occurrence
98
      restored, thus transfering the control flow to the place of occurrence
99
      of the corresponding call to <code>context_save</code>. From the
99
      of the corresponding call to <code>context_save()</code>. From the
100
      perspective of the caller of the corresponding
100
      perspective of the caller of the corresponding
101
      <code>context_save</code>, it looks as though a return from
101
      <code>context_save()</code>, it looks like a return from
102
      <code>context_save</code>. However, this time a return value of 0 is
102
      <code>context_save()</code>. However, this time a return value of 0 is
103
      returned.</para>
103
      returned.</para>
104
    </section>
104
    </section>
105
  </section>
105
  </section>
106
 
106
 
107
  <section>
107
  <section>
Line 134... Line 134...
134
      possibilities. It either runs until it is preemtped, in which case the
134
      possibilities. It either runs until it is preemtped, in which case the
135
      state changes to <constant>Ready</constant>, goes to the
135
      state changes to <constant>Ready</constant>, goes to the
136
      <constant>Sleeping</constant> state by going to sleep or enters the
136
      <constant>Sleeping</constant> state by going to sleep or enters the
137
      <constant>Exiting</constant> state when it reaches termination. When the
137
      <constant>Exiting</constant> state when it reaches termination. When the
138
      thread exits, its kernel structure usually stays in memory, until the
138
      thread exits, its kernel structure usually stays in memory, until the
139
      thread is detached by another thread using <code>thread_detach</code>
139
      thread is detached by another thread using <code>thread_detach()</code>
140
      function. Terminated but undetached threads are in the
140
      function. Terminated but undetached threads are in the
141
      <constant>Undead</constant> state. When the thread is detached or
141
      <constant>Undead</constant> state. When the thread is detached or
142
      detaches itself during its life, it is destroyed in the
142
      detaches itself during its life, it is destroyed in the
143
      <constant>Exiting</constant> state and the <constant>Undead</constant>
143
      <constant>Exiting</constant> state and the <constant>Undead</constant>
144
      state is not reached.<figure float="1">
144
      state is not reached.<figure float="1">
Line 205... Line 205...
205
 
205
 
206
    <section>
206
    <section>
207
      <title>Scheduler Operation</title>
207
      <title>Scheduler Operation</title>
208
 
208
 
209
      <para>The scheduler is invoked either explicitly when a thread calls the
209
      <para>The scheduler is invoked either explicitly when a thread calls the
210
      <code>scheduler</code> function (e.g. goes to sleep or merely wants to
210
      <code>scheduler()</code> function (e.g. goes to sleep or merely wants to
211
      relinquish the processor for a while) or implicitly on a periodic basis
211
      relinquish the processor for a while) or implicitly on a periodic basis
212
      when the generic clock interrupt preempts the current thread. After its
212
      when the generic clock interrupt preempts the current thread. After its
213
      invocation, the scheduler saves the synchronous register context of the
213
      invocation, the scheduler saves the synchronous register context of the
214
      current thread and switches to its private stack. Afterwards, a new
214
      current thread and switches to its private stack. Afterwards, a new
215
      thread is selected according to the scheduling policy. If there is no
215
      thread is selected according to the scheduling policy. If there is no
Line 223... Line 223...
223
      <para>The scheduling policy is implemented in function
223
      <para>The scheduling policy is implemented in function
224
      <code>find_best_thread</code>. This function walks the processor run
224
      <code>find_best_thread</code>. This function walks the processor run
225
      queues from lower towards higher indices and looks for a thread. If the
225
      queues from lower towards higher indices and looks for a thread. If the
226
      visited run queue is empty, it simply searches the next run queue. If it
226
      visited run queue is empty, it simply searches the next run queue. If it
227
      is known in advance that there are no ready threads waiting for
227
      is known in advance that there are no ready threads waiting for
228
      execution, <code>find_best_thread</code> interruptibly halts the
228
      execution, <code>find_best_thread()</code> interruptibly halts the
229
      processor or busy waits until some threads arrive. This process repeats
229
      processor or busy waits until some threads arrive. This process repeats
230
      until <code>find_best_thread</code> succeeds.</para>
230
      until <code>find_best_thread()</code> succeeds.</para>
231
 
231
 
232
      <para>After the best thread is chosen, the scheduler switches to the
232
      <para>After the best thread is chosen, the scheduler switches to the
233
      thread's task and memory management context. Finally, the saved
233
      thread's task and memory management context. Finally, the saved
234
      synchronous register context is restored and the thread runs. Each
234
      synchronous register context is restored and the thread runs. Each
235
      scheduled thread is given a time slice depending on its priority (i.e.
235
      scheduled thread is given a time slice depending on its priority (i.e.