/[rtmk]/rtmk/thread.c
ViewVC logotype

Diff of /rtmk/thread.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.12 by jrydberg, Mon Jan 7 02:45:42 2002 UTC revision 1.13 by jrydberg, Fri Jan 11 22:24:11 2002 UTC
# Line 37  do                                                             \ Line 37  do                                                             \
37    }                                                             \    }                                                             \
38  while (0)  while (0)
39    
40    /* Reaper list for zombie threads.  */
41    
42    static struct queue_entry reaper_list = queue_ctor (reaper_list);
43    static spin_lock_t reaper_lock = SPIN_LOCK_INITIALIZER;
44    
45  /* ???? */  /* ???? */
46    
47  struct sched_policy sched_policies [4];  struct sched_policy sched_policies [4];
# Line 56  static struct kmem_cache *thread_cache; Line 61  static struct kmem_cache *thread_cache;
61  /* Cache for kernel stacks.  */  /* Cache for kernel stacks.  */
62  static struct kmem_cache *stack_cache;  static struct kmem_cache *stack_cache;
63    
64    /* Thread list.  Contains all threads in the system.  */
65    static struct queue_entry thread_list = queue_ctor (thread_list);
66    static spin_lock_t thread_list_lock;
67    
68    
69  /* Wait semantics.  /* Wait semantics.
70    
# Line 102  void Line 111  void
111  reaper_continuation (void)  reaper_continuation (void)
112  {  {
113    /* ??? dead code right now.  */    /* ??? dead code right now.  */
114    thread_sleep (0xdeadbeef, 0, reaper_continuation);    thread_sleep ((int) &reaper_list, 0, reaper_continuation);
115  }  }
116    
117  /* Create a new thread in TASK.  The thread is returned in THREADP.  */  /* Create a new thread in TASK.  The thread is returned in THREADP.  */
# Line 112  thread_create (struct task *task, struct Line 121  thread_create (struct task *task, struct
121  {  {
122    struct thread *thread;    struct thread *thread;
123    kern_return_t kr;    kern_return_t kr;
124      SPL_T spl;
125    
126    thread = kmem_cache_alloc (thread_cache);    thread = kmem_cache_alloc (thread_cache);
127    if (! thread)    if (! thread)
# Line 152  thread_create (struct task *task, struct Line 162  thread_create (struct task *task, struct
162    if (kr != KERN_SUCCESS)    if (kr != KERN_SUCCESS)
163      return kr;      return kr;
164    
165      /* Insert thread into thread list.  */
166    
167      spl = SPLOFF ();
168      spin_lock (&thread_list_lock);
169      queue_enter (&thread_list, thread, struct thread *, allq);
170      spin_unlock (&thread_list_lock);
171      SPLON (spl);
172    
173      trace_count (n_threads++);
174    
175    *threadp = thread;    *threadp = thread;
176    return KERN_SUCCESS;    return KERN_SUCCESS;
177  }  }
178    
179    /* Terminate THREAD.  */
180    
181    kern_return_t
182    thread_terminate (struct thread *thread)
183    {
184      SPL_T spl;
185    
186      /* First check if we should zombify the current running thread.  */
187    
188      if (THREAD_CURRENT () == thread)
189        thread_zombify_running (THREAD_CURRENT ());
190    
191      spl = SPLOFF ();
192      thread_lock (thread);
193    
194    #if 0 /* NCPUS > 1 */
195      /* Check if thread is running on some other processor.  If it does,
196         we send a interprocessor interrupt to that processor.  */
197    
198      if (thread->running_p)
199        {
200          processor_send_terminate_ipi (thread->last_processor, thread);
201          thread_sleep ((int) thread, &thread->lock, 0);
202    
203          SPLON (spl);
204          return KERN_SUCCESS;
205        }
206    #endif
207    
208      /* Thread is not running on any processor -> it is either waiting or
209         on some run queue.  Remove thread from queue and kill it.  */
210    
211      if (thread->sched_state & THREAD_STATE_WAIT)
212        {
213          int event;
214    
215          event = thread->wait_event;
216          if (event)
217            {
218              int hash_index = WAIT_HASH (event);
219              
220              thread_unlock (thread);
221              spin_lock (&wait_locks [hash_index]);
222              thread_lock (thread);
223          
224              if (thread->wait_event == event)
225                {
226                  queue_remove (&wait_queues [hash_index], thread,
227                                struct thread *, waitq);
228                }
229    
230              thread_unlock (thread);
231              spin_unlock (&wait_locks [hash_index]);
232              thread_lock (thread);
233            }
234        }
235      else /* on runq */
236        (*thread->sched_sp->ops->remove_fn) (thread->sched_sp, thread);
237    
238      /* Add thread to reaper daemon zombie list.  Since we no longer will
239         use the RUNQ chain in thread we use that as reaper chain link.  */
240    
241      thread_unlock (thread);
242      spin_lock (&reaper_lock);
243      thread_lock (thread);
244      queue_enter (&reaper_list, thread, struct thread *, runq);
245      thread_unlock (thread);
246      spin_unlock (&reaper_lock);
247    
248      /* Wake up reaper daemon.  */
249    
250      thread_wakeup ((int) &reaper_list);
251    
252      SPLON (spl);
253      return KERN_SUCCESS;
254    }
255    
256    /* Halt running thread THREAD.  This will signal to waiting threads that
257       the thread have become a zombie.  Will put thread on reaper queue.  */
258    
259    kern_return_t
260    thread_zombify_running (struct thread *thread)
261    {
262      SPL_T spl;
263    
264      spl = SPLOFF ();
265    
266      /* Set scheduling state to zombie state.  */
267    
268      thread_lock (thread);
269      thread->sched_state |= THREAD_STATE_ZOMBIE;
270      thread_unlock (thread);
271    
272      /* Add thread to reaper daemon zombie list.  Since we no longer will
273         use the RUNQ chain in thread we use that as reaper chain link.  */
274    
275      spin_lock (&reaper_lock);
276      thread_lock (thread);
277      queue_enter (&reaper_list, thread, struct thread *, runq);
278      thread_unlock (thread);
279      spin_unlock (&reaper_lock);
280    
281      /* Before waking up the reaper, we singal all threads waiting for this
282         to finish.   If we get preempted here, there's nothing to do, right?  */
283    
284      thread_wakeup ((int) thread);
285    
286      /* Wake up reaper daemon.  */
287    
288      thread_wakeup ((int) &reaper_list);
289    
290      /* Block here, we will never get any further.  */
291    
292      thread_block (0);
293      panic ("??? after zombie state! should not be possible!");
294    
295      return KERN_SUCCESS;
296    }
297    
298  /* Return send right name to current thread.  */  /* Return send right name to current thread.  */
299    
300  rtmk_port_t  rtmk_port_t
# Line 200  thread_continue (struct thread *old_thre Line 339  thread_continue (struct thread *old_thre
339  {  {
340    void (*continuation) () = THREAD_CURRENT()->swap_fn;    void (*continuation) () = THREAD_CURRENT()->swap_fn;
341    
   /* We must dispatch the old thread and then  
      call the current thread's continuation.  
      There might not be an old thread, if we are  
      the first thread to run on this processor.  */  
   
 #if 0  
   if (old_thread != 0)  
     thread_dispatch (old_thread);  
 #endif  
   
342    SPL0 ();    SPL0 ();
343    (*continuation) ();    (*continuation) ();
344  }  }
# Line 255  thread_invoke (struct thread *old_thread Line 384  thread_invoke (struct thread *old_thread
384            STACK_HANDOFF (old_thread, new_thread);            STACK_HANDOFF (old_thread, new_thread);
385            old_thread->sched_state |= THREAD_STATE_SWAPPED;            old_thread->sched_state |= THREAD_STATE_SWAPPED;
386    
387            switch (old_thread->sched_state & ~THREAD_STATE_SWAPPED)            if ((old_thread->sched_state & THREAD_SCHED_STATE)
388              {                == THREAD_STATE_RUN)
389              case THREAD_STATE_RUN:              thread_setrun (old_thread, false);
               thread_setrun (old_thread, false);  
               break;  
             }  
390          }          }
391        else        else
392          {          {
393            switch (old_thread->sched_state & ~THREAD_STATE_SWAPPED)            if ((old_thread->sched_state & THREAD_SCHED_STATE)
394              {                == THREAD_STATE_RUN)
395              case THREAD_STATE_RUN:              thread_setrun (old_thread, false);
               thread_setrun (old_thread, false);  
               break;  
             }  
396          }          }
397      }      }
398    
# Line 283  thread_invoke (struct thread *old_thread Line 406  thread_invoke (struct thread *old_thread
406            new_thread->sched_state &= ~THREAD_STATE_SWAPPED;            new_thread->sched_state &= ~THREAD_STATE_SWAPPED;
407          }          }
408    
409        switch (old_thread->sched_state & ~THREAD_STATE_SWAPPED)        if ((old_thread->sched_state & THREAD_SCHED_STATE)
410          {            == THREAD_STATE_RUN)
411          case THREAD_STATE_RUN:          thread_setrun (old_thread, false);
           thread_setrun (old_thread, false);  
           break;  
         }  
412      }      }
413        
414    trace_count (context_switches++);    trace_count (context_switches++);
# Line 550  thread_go (struct thread *new_thread, vo Line 670  thread_go (struct thread *new_thread, vo
670    
671    spl = SPLOFF ();    spl = SPLOFF ();
672    
673    while (! thread_invoke (thread, continuation, new_thread));    while (! thread_invoke (thread, continuation, new_thread))
674      new_thread = thread_select (PROCESSOR_CURRENT ());      new_thread = thread_select (PROCESSOR_CURRENT ());
675    
676    SPLON (spl);    SPLON (spl);
# Line 764  thread_setrun (struct thread *thread, bo Line 884  thread_setrun (struct thread *thread, bo
884    processor = thread->last_processor;    processor = thread->last_processor;
885    if (processor)    if (processor)
886      {      {
887          /* If the last processor is the current one, check if we can preempt it.  */
888    
889          if (processor == PROCESSOR_CURRENT ())
890            {
891              if ((processor->state == PROCESSOR_STATE_RUNNING
892                   && thread->sched_premul > processor->current_thread->sched_premul)
893                  || processor->state == PROCESSOR_STATE_IDLE)
894                {
895                  trace_count (cpu_switch_hits++);
896                  thread_go (thread, 0);
897                  return;
898                }
899            }
900    
901        if (processor->state == PROCESSOR_STATE_IDLE)        if (processor->state == PROCESSOR_STATE_IDLE)
902          {          {
903            processor->state = PROCESSOR_STATE_DISPATCH;            processor->state = PROCESSOR_STATE_DISPATCH;
904            processor_send_dispatch_ipi (processor, thread);            processor_send_dispatch_ipi (processor, thread);
905              trace_count (cpu_switch_hits++);
906            return;            return;
907          }          }
908        else if (processor->state == PROCESSOR_STATE_RUNNING &&        else if (processor->state == PROCESSOR_STATE_RUNNING &&
909                 thread->sched_premul > processor->current_thread->sched_premul)                 thread->sched_premul > processor->current_thread->sched_premul)
910          {          {
911              trace_printf ("last cpu %d current prio %x, new prio %x",
912                            processor->cpu_id, processor->current_thread->sched_premul,
913                            thread->sched_premul);
914    
915            processor->state = PROCESSOR_STATE_DISPATCH;            processor->state = PROCESSOR_STATE_DISPATCH;
916            processor_send_dispatch_ipi (processor, thread);            processor_send_dispatch_ipi (processor, thread);
917              trace_count (cpu_switch_hits++);
918              return;
919          }          }
920      }      }
921    
# Line 796  thread_setrun (struct thread *thread, bo Line 937  thread_setrun (struct thread *thread, bo
937          {          {
938            processor->state = PROCESSOR_STATE_DISPATCH;            processor->state = PROCESSOR_STATE_DISPATCH;
939            processor_send_dispatch_ipi (processor, thread);            processor_send_dispatch_ipi (processor, thread);
940              return;
941            }
942    #if 0
943          else if (processor->state == PROCESSOR_STATE_RUNNING)
944            {
945              trace_printf ("cpu %d current prio %x, new prio %x",
946                            i, processor->current_thread->sched_premul,
947                            thread->sched_premul);
948          }          }
949    #endif
950      }      }
951  #endif  #endif
952    

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26