Index: trunk/kernel/kern/scheduler.c
===================================================================
--- trunk/kernel/kern/scheduler.c	(revision 278)
+++ trunk/kernel/kern/scheduler.c	(revision 279)
@@ -41,8 +41,8 @@
     sched->k_threads_nr   = 0;
 
-    sched->current        = NULL;
-    sched->idle           = NULL;
-    sched->u_last         = NULL;
-    sched->k_last         = NULL;
+    sched->current        = CURRENT_THREAD;
+    sched->idle           = NULL;             // initialized in kernel_init()
+    sched->u_last         = NULL;             // initialized in sched_register_thread()
+    sched->k_last         = NULL;             // initialized in sched_register_thread()
 
     // initialise threads lists
@@ -62,14 +62,21 @@
     spinlock_lock( &sched->lock );
 
-    // register thread
     if( type == THREAD_USER )
     {
+        // register thread in scheduler user list
         list_add_last( &sched->u_root , &thread->sched_list );
         sched->u_threads_nr++;
+
+        // initialize u_last field if first user thread
+        if( sched->u_last == NULL ) sched->u_last = &thread->sched_list;
     }
     else // kernel thread
     {
+        // register thread in scheduler kernel list
         list_add_last( &sched->k_root , &thread->sched_list );
         sched->k_threads_nr++;
+
+        // initialize k_last field if first kernel thread
+        if( sched->k_last == NULL ) sched->k_last = &thread->sched_list; 
     }
 
@@ -89,14 +96,21 @@
     spinlock_lock( &sched->lock );
 
-    // remove thread
     if( type == THREAD_USER )
     {
+        // remove thread from user list
         list_unlink( &thread->sched_list );
         sched->u_threads_nr--;
+
+        // reset the u_last field if list empty
+        if( sched->u_threads_nr == 0 ) sched->u_last = NULL;
     }
     else // kernel thread 
     {
+        // remove thread from kernel list
         list_unlink( &thread->sched_list );
         sched->k_threads_nr--;
+
+        // reset the k_last field if list empty
+        if( sched->k_threads_nr == 0 ) sched->k_last = NULL;
     }
 
@@ -140,56 +154,64 @@
     list_entry_t * last;
 
-    // first scan the kernel threads
-    last    = sched->k_last;
-    current = sched->k_last;
-    do
-    {
-        // get next entry in kernel list
-        current = list_next( &sched->k_root , current );
-
-        // skip the list root that does not contain a thread
-        if( current == NULL ) continue;
-
-        // get thread pointer
-        thread = LIST_ELEMENT( current , thread_t , sched_list );
-
-        // return thread if not blocked
-        if( thread->blocked == 0 ) 
+    // first : scan the kernel threads list,
+    // only if this list is not empty 
+    if( list_is_empty( &sched->k_root ) == false )
+    {
+        last    = sched->k_last;
+        current = sched->k_last;
+        do
         {
-            // release lock 
-            spinlock_unlock( &sched->lock );
-            return thread;
+            // get next entry in kernel list
+            current = list_next( &sched->k_root , current );
+
+            // skip the root that does not contain a thread
+            if( current == NULL ) current = sched->k_root.next;
+
+            // get thread pointer for this entry
+            thread = LIST_ELEMENT( current , thread_t , sched_list );
+
+            // return thread if runnable
+            if( thread->blocked == 0 ) 
+            {
+                // release lock 
+                spinlock_unlock( &sched->lock );
+                return thread;
+            }
         }
-    }
-    while( current != last );
-
-    // second scan the user threads
-    last    = sched->u_last;
-    current = sched->u_last;
-    do
-    {
-        // get next entry in user list
-        current = list_next( &sched->u_root , current );
-
-        // skip the list root that does not contain a thread
-        if( current == NULL ) continue;
-
-        // get thread pointer
-        thread = LIST_ELEMENT( current , thread_t , sched_list );
-
-        // return thread if not blocked
-        if( thread->blocked == 0 )
+        while( current != last );
+    }
+
+    // second : scan the user threads list,
+    // only if this list is not empty 
+    if( list_is_empty( &sched->u_root ) == false )
+    {
+        last    = sched->u_last;
+        current = sched->u_last;
+        do
         {
-            // release lock 
-            spinlock_unlock( &sched->lock );
-            return thread;
+            // get next entry in user list
+            current = list_next( &sched->u_root , current );
+
+            // skip the root that does not contain a thread
+            if( current == NULL ) current = sched->u_root.next;
+
+            // get thread pointer for this entry
+            thread = LIST_ELEMENT( current , thread_t , sched_list );
+
+            // return thread if runnable
+            if( thread->blocked == 0 )
+            {
+                // release lock 
+                spinlock_unlock( &sched->lock );
+                return thread;
+            }
         }
-    }
-    while( current != last );
+        while( current != last );
+    }
 
     // release lock 
     spinlock_unlock( &sched->lock );
 
-    // third, return idle thread if no runnable thread
+    // third : return idle thread if no runnable thread
     return sched->idle;
 
@@ -234,4 +256,5 @@
     thread_t    * current = CURRENT_THREAD;
     core_t      * core    = current->core;
+    scheduler_t * sched   = &core->scheduler;
 
     if( thread_can_yield() == false )
@@ -265,9 +288,14 @@
                __FUNCTION__, core->lid, local_cxy, current->trdid, next->trdid );
 
-    // switch contexts if new thread
+    // switch contexts and update scheduler state if new thread
 	if( next != current )  
 	{
         hal_cpu_context_save( current );
         hal_cpu_context_restore( next );
+
+        if( current->type == THREAD_USER ) sched->u_last = &current->sched_list;
+        else                               sched->k_last = &current->sched_list;
+
+        sched->current = next;
 	}
 
