Re: [pok-devel] Problem with the POK scheduler...

[ Thread Index | Date Index | More lists.tuxfamily.org/pok-devel Archives ]


Hello everybody

the attached patch fixes the problem I have seen in the scheduler. It validates the test suite and has no known problems

however since it deals in the intricacies of the scheduler I would like to have as much review/testing as possible

the problem was that the current_partition global variable was changed too early.

the new philosophy is that elect_partition will not change the global state, nor will elect_thread.

thus, when elect_thread is called, current_partition and current_thread are still set to the old thread/partition.

All changes are done after the decisions are taken.

Please review and feedback so I can commit this changes soon

    Regards

    Jérémy Rosen

fight key loggers : write some perl using vim

----- Mail original -----
> Hello everybody
>
> while debugging a problem with partition initialisation I stumbled on
> a limitation in the POK scheduler that might be a serious bug... I
> am trying to find all the ins and outs of that bug but I would
> likely take any advice...
>
>
>
> THE SYMPTOMS
>
> I have two partitions (A and B) with main threads (Amain and Bmain)
>
> A is started and runs Amain
> - end of window, Amain isn't done yet
> B is started and runs Bmain
> Bmain set the partition mode to normal
>
> Bug : immediately Amain starts axecuting again within B's time slot
> (which isn't over yet)
>
>
> WHAT IS ACTUALLY HAPPENING
>
> when Amain is executing and is swapped out, it is stored in
> A.current_thread which is the IDLE_THREAD at this point. As a
> consequence, when Bmain is done, it runs the idle thread which
> contains Amain's code
>
> The problem is that pok_sched_elect_partition does the actual
> partition switching and that confuses the pok_sched_elect_thread
> function.
>
> the pok_sched_elect_thread function seems to only work properly when
> a change of partition occurs only if the partition that is being
> left is running the idle thread.
>
>
> so...
>
>
> * is this a design choice ?
> * has anybody encountered that ?
> * any advice on fixing it ?
>
> I am working on a fix but it's complicated and touches the whole
> scheduler logic (mainly because of unsafe assumptions with
> current_thread and prev_current_thread which are assumed to be part
> of the current partition) so any word of wisdom would be welcome
>
>     Regards
>
>     Jérémy Rosen
>
> fight key loggers : write some perl using vim
>
>
>
diff --git a/pok/trunk/kernel/core/debug.c b/pok/trunk/kernel/core/debug.c
index f218758..f28b4e3 100644
--- a/pok/trunk/kernel/core/debug.c
+++ b/pok/trunk/kernel/core/debug.c
@@ -54,7 +54,7 @@ void pok_debug_print_current_state ()
    printf ("Base vaddr           : 0x%x\n", POK_CURRENT_PARTITION.base_vaddr);
    printf ("Size                 : %d\n", POK_CURRENT_PARTITION.size);
    printf ("Current thread       : %d\n", POK_CURRENT_PARTITION.current_thread);
-   printf ("Prev current thread  : %d\n", POK_CURRENT_PARTITION.prev_current_thread);
+   printf ("Prev current thread  : %d\n", POK_CURRENT_PARTITION.prev_thread);
    printf ("Main thread          : %d\n", POK_CURRENT_PARTITION.thread_main);
    printf ("Main thread entry    : 0x%x\n", POK_CURRENT_PARTITION.thread_main_entry);
    printf ("Partition threads sp :");
diff --git a/pok/trunk/kernel/core/partition.c b/pok/trunk/kernel/core/partition.c
index dc9ed5d..255f67b 100644
--- a/pok/trunk/kernel/core/partition.c
+++ b/pok/trunk/kernel/core/partition.c
@@ -97,7 +97,7 @@ void pok_partition_reinit (const uint8_t pid)
 
    pok_partitions[pid].thread_index = 0;
    pok_partitions[pid].current_thread = pok_partitions[pid].thread_index_low;
-   pok_partitions[pid].prev_current_thread =  IDLE_THREAD;
+   pok_partitions[pid].prev_thread =  IDLE_THREAD; // breaks the rule of prev_thread not being idle, but it's just for init
 
 #ifdef POK_NEEDS_ERROR_HANDLING
    pok_partitions[pid].thread_error = 0;
@@ -200,7 +200,7 @@ pok_ret_t pok_partition_init ()
       pok_partitions[i].thread_index      = 0;
       pok_partitions[i].thread_main       = 0;
       pok_partitions[i].current_thread    = IDLE_THREAD;
-      pok_partitions[i].prev_current_thread    = IDLE_THREAD;
+      pok_partitions[i].prev_thread       = IDLE_THREAD; // breaks the rule of prev_thread not being idle, but it's just for init
 
 #ifdef POK_NEEDS_SCHED_HFPPS
       pok_partitions[i].payback = 0;
@@ -241,6 +241,7 @@ pok_ret_t pok_partition_init ()
 #endif
 
       pok_partition_setup_main_thread (i);
+      pok_partitions[i].current_thread    = pok_partitions[i].thread_main;
    }
 
    return POK_ERRNO_OK;
diff --git a/pok/trunk/kernel/core/sched.c b/pok/trunk/kernel/core/sched.c
index cd93d57..d550253 100644
--- a/pok/trunk/kernel/core/sched.c
+++ b/pok/trunk/kernel/core/sched.c
@@ -65,7 +65,6 @@ uint64_t           pok_sched_slots[POK_CONFIG_SCHEDULING_NBSLOTS]
 uint8_t           pok_sched_slots_allocation[POK_CONFIG_SCHEDULING_NBSLOTS]
                               = (uint8_t[]) POK_CONFIG_SCHEDULING_SLOTS_ALLOCATION;
 
-uint32_t          prev_current_thread;
 pok_sched_t       pok_global_sched;
 uint64_t          pok_sched_next_deadline;
 uint64_t          pok_sched_next_major_frame;
@@ -129,8 +128,9 @@ uint8_t pok_sched_get_priority_max (const pok_sched_t sched_type)
 }
 
 #ifdef POK_NEEDS_PARTITIONS
-pok_partition_t*	pok_elect_partition()
+uint8_t	pok_elect_partition()
 {
+  uint8_t next_partition = POK_SCHED_CURRENT_PARTITION;
 # if POK_CONFIG_NB_PARTITIONS > 1
   uint64_t now = POK_GETTICK();
 
@@ -151,39 +151,33 @@ pok_partition_t*	pok_elect_partition()
     *  FIXME : current debug session about exceptions-handled
       printf ("Switch from partition %d to partition %d\n", pok_current_partition, pok_sched_current_slot);
       printf ("old current thread = %d\n", POK_SCHED_CURRENT_THREAD);
-      printf ("old prev current thread = %d\n", prev_current_thread);
 
       printf ("new current thread = %d\n", pok_partitions[pok_sched_current_slot].current_thread);
-      printf ("new prev current thread = %d\n", pok_partitions[pok_sched_current_slot].prev_current_thread);
+      printf ("new prev current thread = %d\n", pok_partitions[pok_sched_current_slot].prev_thread);
       */
-    pok_partitions[pok_current_partition].prev_current_thread = prev_current_thread;
-    pok_partitions[pok_current_partition].current_thread = POK_SCHED_CURRENT_THREAD;
-
-    pok_current_partition = pok_sched_slots_allocation[pok_sched_current_slot];
-
-    prev_current_thread = pok_partitions[pok_current_partition].prev_current_thread;
-    current_thread = pok_partitions[pok_current_partition].current_thread;
+    next_partition = pok_sched_slots_allocation[pok_sched_current_slot];
 
 #ifdef POK_NEEDS_SCHED_HFPPS
-   if (pok_partitions[pok_current_partition].payback > 0) // pay back!
+   if (pok_partitions[next_partition].payback > 0) // pay back!
    {
      // new deadline
-     pok_sched_next_deadline -= pok_partitions[pok_current_partition].payback;
-     pok_partitions[pok_current_partition].payback = 0;
+     pok_sched_next_deadline -= pok_partitions[next_partition].payback;
+     pok_partitions[next_partition].payback = 0;
    }
 #endif /* POK_NEEDS_SCHED_HFPPS */
 
   }
 # endif /* POK_CONFIG_NB_PARTITIONS > 1 */
 
-  return (&(pok_partitions[pok_current_partition]));
+  return next_partition;
 }
 #endif /* POK_NEEDS_PARTITIONS */
 
 #ifdef POK_NEEDS_PARTITIONS
-uint32_t	pok_elect_thread(pok_partition_t* current_partition)
+uint32_t	pok_elect_thread(uint8_t new_partition_id)
 {
    uint64_t now = POK_GETTICK();
+   pok_partition_t* new_partition = &(pok_partitions[new_partition_id]);
 
 
    /*
@@ -194,9 +188,9 @@ uint32_t	pok_elect_thread(pok_partition_t* current_partition)
                          * type
                          */
    pok_thread_t* thread;
-   for (i = 0; i < pok_partitions[pok_current_partition].nthreads; i++)
+   for (i = 0; i < new_partition->nthreads; i++)
    {
-     thread = &(pok_threads[current_partition->thread_index_low + i]);
+     thread = &(pok_threads[new_partition->thread_index_low + i]);
 
 #if defined (POK_NEEDS_LOCKOBJECTS) || defined (POK_NEEDS_PORTS_QUEUEING) || defined (POK_NEEDS_PORTS_SAMPLING)
      if ((thread->state == POK_STATE_WAITING) && (thread->wakeup_time <= now))
@@ -217,32 +211,31 @@ uint32_t	pok_elect_thread(pok_partition_t* current_partition)
     * We elect the thread to be executed.
     */
    uint32_t elected;
-   switch (current_partition->mode)
+   switch (new_partition->mode)
    {
       case POK_PARTITION_MODE_INIT_COLD:
       case POK_PARTITION_MODE_INIT_WARM:
 #ifdef POK_NEEDS_ERROR_HANDLING
-         if ((current_partition->thread_error != 0) &&
-             (pok_threads[current_partition->thread_error].state != POK_STATE_STOPPED))
+         if ((new_partition->thread_error != 0) &&
+             (pok_threads[new_partition->thread_error].state != POK_STATE_STOPPED))
          {
-            elected = current_partition->thread_error;
+            elected = new_partition->thread_error;
          }
          else
          {
-            elected = current_partition->thread_main;
+            elected = new_partition->thread_main;
          }
 #endif
 
-         elected = current_partition->thread_main;
+         elected = new_partition->thread_main;
          break;
 
       case POK_PARTITION_MODE_NORMAL:
 #ifdef POK_NEEDS_ERROR_HANDLING
-         if ((POK_SCHED_CURRENT_THREAD == POK_CURRENT_PARTITION.thread_error) && 
-             (POK_CURRENT_THREAD.state == POK_STATE_RUNNABLE))
+         if ((new_partition->current_thread == new_partition->thread_error) && 
+             (pok_threads[new_partition->current_thread].state == POK_STATE_RUNNABLE))
          {
-            elected = POK_CURRENT_PARTITION.thread_error;
-            POK_CURRENT_PARTITION.current_thread = elected;
+            elected = new_partition->thread_error;
             break;
          }
 #endif
@@ -262,15 +255,16 @@ uint32_t	pok_elect_thread(pok_partition_t* current_partition)
                POK_CURRENT_THREAD.state = POK_STATE_WAIT_NEXT_ACTIVATION;
             }
          }
-         elected = POK_CURRENT_PARTITION.sched_func (current_partition->thread_index_low,
-                                                     current_partition->thread_index_high);
+         elected = new_partition->sched_func (new_partition->thread_index_low,
+                                                     new_partition->thread_index_high,
+						     new_partition->prev_thread,
+						     new_partition->current_thread);
 #ifdef POK_NEEDS_INSTRUMENTATION
-          if ( (elected != IDLE_THREAD) && (elected != POK_CURRENT_PARTITION.thread_main))
+          if ( (elected != IDLE_THREAD) && (elected != new_partition->thread_main))
           {
             pok_instrumentation_running_task (elected);
           }
 #endif
-         POK_CURRENT_PARTITION.current_thread = elected;
 
          break;
 
@@ -298,6 +292,7 @@ uint32_t	pok_elect_thread(pok_partition_t* current_partition)
 void pok_sched()
 {
   uint32_t elected_thread = 0;
+  uint8_t elected_partition = POK_SCHED_CURRENT_PARTITION;
 
 #ifdef POK_NEEDS_SCHED_HFPPS
   uint64_t now = POK_GETTICK();
@@ -315,10 +310,18 @@ void pok_sched()
   else /* overmegadirty */
 #endif /* POK_NEEDS_SCHED_HFPPS */
   {
-    pok_partition_t* elected_partition = pok_elect_partition();
+  
+    elected_partition = pok_elect_partition();
     elected_thread = pok_elect_thread(elected_partition);
   }
 
+   pok_current_partition = elected_partition;
+   if(pok_partitions[pok_current_partition].current_thread != elected_thread) {
+	   if(pok_partitions[pok_current_partition].current_thread != IDLE_THREAD) {
+		   pok_partitions[pok_current_partition].prev_thread = pok_partitions[pok_current_partition].current_thread;
+	   }
+	   pok_partitions[pok_current_partition].current_thread = elected_thread;
+   }
   pok_sched_context_switch(elected_thread);
 }
 #else
@@ -360,6 +363,7 @@ void pok_sched_context_switch (const uint32_t elected_id)
    {
       return;
    }
+
    current_sp = &POK_CURRENT_THREAD.sp;
    new_sp = pok_threads[elected_id].sp;
 /*
@@ -376,24 +380,12 @@ void pok_sched_context_switch (const uint32_t elected_id)
 }
 
 #ifdef POK_NEEDS_SCHED_RMS
-uint32_t pok_sched_part_rms (const uint32_t index_low, const uint32_t index_high)
+uint32_t pok_sched_part_rms (const uint32_t index_low, const uint32_t index_high,const uint32_t __attribute__((unused)) prev_thread,const uint32_t __attribute__((unused)) current_thread)
 {
    uint32_t res;
 #ifdef POK_NEEDS_DEBUG
    uint32_t from;
-#endif
-
-   if (POK_SCHED_CURRENT_THREAD == IDLE_THREAD)
-   {
-      res = prev_current_thread;
-   }
-   else
-   {
-      res = POK_SCHED_CURRENT_THREAD;
-   }
-
-#ifdef POK_NEEDS_DEBUG
-   from = res;
+   from = prev_thread;
 #endif
 
    res= index_low;
@@ -412,10 +404,6 @@ uint32_t pok_sched_part_rms (const uint32_t index_low, const uint32_t index_high
    if ((res == index_low) && (pok_threads[res].state != POK_STATE_RUNNABLE))
    {
       res = IDLE_THREAD;
-      if (POK_SCHED_CURRENT_THREAD != IDLE_THREAD)
-      {
-         prev_current_thread = POK_SCHED_CURRENT_THREAD;
-      }
    }
 
 #ifdef POK_NEEDS_DEBUG
@@ -441,25 +429,25 @@ uint32_t pok_sched_part_rms (const uint32_t index_low, const uint32_t index_high
 #endif /* POK_NEEDS_SCHED_RMS */
 
 
-uint32_t pok_sched_part_rr (const uint32_t index_low, const uint32_t index_high)
+uint32_t pok_sched_part_rr (const uint32_t index_low, const uint32_t index_high,const uint32_t prev_thread,const uint32_t current_thread)
 {
    uint32_t res;
    uint32_t from;
 
-   if (POK_SCHED_CURRENT_THREAD == IDLE_THREAD)
+   if (current_thread == IDLE_THREAD)
    {
-      res = prev_current_thread;
+      res = prev_thread;
    }
    else
    {
-      res = POK_SCHED_CURRENT_THREAD;
+      res = current_thread;
    }
 
    from = res;
 
-   if ((POK_CURRENT_THREAD.remaining_time_capacity > 0) && (POK_CURRENT_THREAD.state == POK_STATE_RUNNABLE))
+   if ((pok_threads[current_thread].remaining_time_capacity > 0) && (pok_threads[current_thread].state == POK_STATE_RUNNABLE))
    {
-      return POK_SCHED_CURRENT_THREAD;
+      return current_thread;
    }
 
    do
@@ -475,10 +463,6 @@ uint32_t pok_sched_part_rr (const uint32_t index_low, const uint32_t index_high)
    if ((res == from) && (pok_threads[res].state != POK_STATE_RUNNABLE))
    {
       res = IDLE_THREAD;
-      if (POK_SCHED_CURRENT_THREAD != IDLE_THREAD)
-      {
-         prev_current_thread = POK_SCHED_CURRENT_THREAD;
-      }
    }
    return res;
 }
diff --git a/pok/trunk/kernel/include/core/partition.h b/pok/trunk/kernel/include/core/partition.h
index 93e7bc0..40e85e2 100644
--- a/pok/trunk/kernel/include/core/partition.h
+++ b/pok/trunk/kernel/include/core/partition.h
@@ -82,10 +82,10 @@ typedef struct
 
    pok_sched_t           sched;       /**< The associated for the partition to schedule its threads */
 
-   uint32_t (*sched_func)(uint32_t low, uint32_t high); /**< Scheduling function to scheduler threads */
+   uint32_t (*sched_func)(uint32_t low, uint32_t high,uint32_t prev_thread, uint32_t cur_thread); /**< Scheduling function to scheduler threads */
 
    uint64_t              activation;                    /**< Last activation time of the partition */
-   uint32_t              prev_current_thread;           /**< member for the scheduler (previous scheduled thread inside the partition */
+   uint32_t              prev_thread;           /**< member for the scheduler (previous scheduled real thread inside the partition,i.e not the idle thread */
    uint32_t              current_thread;                /**< member for the scheduler (current executed thread inside the partition */
 
    uint32_t               thread_index_low;    /**< The low index in the threads table */
diff --git a/pok/trunk/kernel/include/core/sched.h b/pok/trunk/kernel/include/core/sched.h
index 4180e5e..80432b2 100644
--- a/pok/trunk/kernel/include/core/sched.h
+++ b/pok/trunk/kernel/include/core/sched.h
@@ -54,8 +54,8 @@ uint8_t pok_sched_get_priority_max (const pok_sched_t sched_type);
 
 /* Scheduler election method */
 uint8_t pok_sched_election (void);
-uint32_t pok_sched_part_rr (const uint32_t ,const uint32_t);
-uint32_t pok_sched_part_rms (const uint32_t ,const uint32_t);
+uint32_t pok_sched_part_rr (const uint32_t ,const uint32_t,const uint32_t prev_thread,const uint32_t current_thread);
+uint32_t pok_sched_part_rms (const uint32_t ,const uint32_t,const uint32_t prev_thread,const uint32_t current_thread);
 
 /* Context switch functions */
 void pok_sched_context_switch (const uint32_t);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/