[pok-devel] DELAYED_START implementation

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


hello everybody

I am now finishing the DELAYED_START implementation started by Matias. 

I have a working implementation (patch attached that I have been stress-testing for some time, and that seems to work. However I would be grateful if someone could do some independant proofreading/testing before I commit. This thing is a bit tricky especially around the scheduler timing calculations and I would be grateful if somebody could proofread that.

In particular ARIC specify that wakeup calculations should be based on the partition's next scheduling. I have based that on partition.activation+POK_CONFIG_MAJOR_FRAME but I am not sure that partition.activation is correctly set when the partition has not been started and if I can rely on that to calculate the partition's next activation time...

thx for the help

Jérémy 


fight key loggers : write some perl using vim

Index: misc/release-files
===================================================================
--- misc/release-files	(révision 42)
+++ misc/release-files	(copie de travail)
@@ -203,6 +203,7 @@
 libpok/core/threadsleep.c
 libpok/core/threadperiod.c
 libpok/core/threadstatus.c
+libpok/core/threaddelayedstart.c
 libpok/core/threadpriority.c
 libpok/core/timecomputedeadline.c
 libpok/core/timeget.c
Index: kernel/core/thread.c
===================================================================
--- kernel/core/thread.c	(révision 42)
+++ kernel/core/thread.c	(copie de travail)
@@ -101,6 +101,7 @@
 #endif
 
    pok_threads[KERNEL_THREAD].priority	   = pok_sched_get_priority_min(0);
+   pok_threads[KERNEL_THREAD].base_priority	   = pok_sched_get_priority_min(0);
    pok_threads[KERNEL_THREAD].state		   = POK_STATE_RUNNABLE;
    pok_threads[KERNEL_THREAD].next_activation = 0;
 
@@ -111,7 +112,7 @@
    pok_threads[IDLE_THREAD].remaining_time_capacity    = 0;
    pok_threads[IDLE_THREAD].wakeup_time		       = 0;
    pok_threads[IDLE_THREAD].entry		       = pok_arch_idle;
-   pok_threads[IDLE_THREAD].priority		       = pok_sched_get_priority_min(0);
+   pok_threads[IDLE_THREAD].base_priority		       = pok_sched_get_priority_min(0);
    pok_threads[IDLE_THREAD].state		       = POK_STATE_RUNNABLE;
 
    pok_threads[IDLE_THREAD].sp			       = pok_context_create
@@ -166,6 +167,7 @@
     if ((attr->priority <= pok_sched_get_priority_max (pok_partitions[partition_id].sched)) && (attr->priority >= pok_sched_get_priority_min (pok_partitions[partition_id].sched)))
    {
       pok_threads[id].priority      = attr->priority;
+      pok_threads[id].base_priority      = attr->priority;
    }
 
    if (attr->period > 0)
@@ -300,6 +302,52 @@
 }
 #endif
 
+pok_ret_t pok_thread_delayed_start (const uint32_t id, const uint32_t ms)
+{
+  if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
+    return POK_ERRNO_THREADATTR;
+  pok_threads[id].priority = pok_threads[id].base_priority;
+  //reset stack
+  pok_context_reset(POK_USER_STACK_SIZE,pok_threads[id].init_stack_addr);
+  if ((long long)pok_threads[id].period == -1) //-1 <==> ARINC INFINITE_TIME_VALUE
+    {
+      if (pok_partitions[pok_threads[id].partition].mode == POK_PARTITION_MODE_NORMAL)
+  	{
+  	  if (ms == 0)
+  	    {
+  	      pok_threads[id].state = POK_STATE_RUNNABLE;
+  	      pok_threads[id].end_time = POK_GETTICK() + pok_threads[id].time_capacity;
+  	    }
+  	  else
+  	    {
+  	      pok_threads[id].state = POK_STATE_WAITING;
+  	      pok_threads[id].wakeup_time = ms;
+  	    }
+	  //the preemption is always enabled so
+  	  pok_sched();
+  	}
+      else //the partition mode is cold or warm start
+  	{
+  	  pok_threads[id].state = POK_STATE_WAITING;
+	  pok_threads[id].wakeup_time = ms;
+  	}
+    }
+  else
+    {
+      if (pok_partitions[pok_threads[id].partition].mode == POK_PARTITION_MODE_NORMAL)
+	    { // set the first release point
+	      pok_threads[id].next_activation = ms + POK_GETTICK();
+	      pok_threads[id].end_time = pok_threads[id].deadline + pok_threads[id].next_activation;
+	    }
+      else
+	   {
+	     pok_threads[id].state = POK_STATE_WAITING;
+	     pok_threads[id].wakeup_time = ms;
+	   }
+    }
+  return POK_ERRNO_OK;
+}
+
 pok_ret_t pok_thread_get_status (const uint32_t id, pok_thread_attr_t *attr)
 {
   if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
Index: kernel/core/partition.c
===================================================================
--- kernel/core/partition.c	(révision 42)
+++ kernel/core/partition.c	(copie de travail)
@@ -37,6 +37,7 @@
 #include <core/loader.h>
 #include <core/partition.h>
 #include <core/instrumentation.h>
+#include <core/time.h>
 
 #include <libc.h>
 
@@ -273,6 +274,26 @@
 
          pok_partitions[pid].mode = mode;  /* Here, we change the mode */
 
+	 pok_thread_t* thread;
+	 unsigned int i;
+	 for (i = 0; i < pok_partitions[pok_current_partition].nthreads; i++)
+	 {
+		 thread = &(pok_threads[POK_CURRENT_PARTITION.thread_index_low + i]);
+		 if ((long long)thread->period == -1) {//-1 <==> ARINC INFINITE_TIME_VALUE
+			 if(thread->state == POK_STATE_WAITING) { // delayed start, the delay is in the wakeup time
+				 if(!thread->wakeup_time) {
+					 thread->state = POK_STATE_RUNNABLE;
+				 }
+				 thread->wakeup_time += POK_GETTICK();
+				 thread->end_time =  thread->wakeup_time + thread->time_capacity;
+			 }
+		 } else {
+			 if(thread->state == POK_STATE_WAITING) { // delayed start, the delay is in the wakeup time
+				 thread->wakeup_time += POK_CONFIG_SCHEDULING_MAJOR_FRAME + POK_CURRENT_PARTITION.activation;
+				 thread->end_time =  thread->wakeup_time + thread->time_capacity;
+			 }
+		 }
+	 }
          pok_sched_stop_thread (pok_partitions[pid].thread_main);
          /* We stop the thread that call this change. All the time,
           * the thread that init this request is the init thread.
Index: kernel/core/syscall.c
===================================================================
--- kernel/core/syscall.c	(révision 42)
+++ kernel/core/syscall.c	(copie de travail)
@@ -125,6 +125,9 @@
 	      return pok_thread_get_status (args->arg1, (pok_thread_attr_t*) (args->arg2 + infos->base_addr));
          break;
 
+   case POK_SYSCALL_THREAD_DELAYED_START:
+     return pok_thread_delayed_start (args->arg1, args->arg2);
+     break;
    case POK_SYSCALL_THREAD_SET_PRIORITY:
 	   return pok_thread_set_priority (args->arg1, args->arg2);
 	   break;
Index: kernel/arch/ppc/thread.c
===================================================================
--- kernel/arch/ppc/thread.c	(révision 42)
+++ kernel/arch/ppc/thread.c	(copie de travail)
@@ -51,4 +51,24 @@
   return (uint32_t)sp;
 }
 
+uint32_t pok_context_reset(uint32_t stack_size,
+			    uint32_t stack_addr)
+{
+  context_t* sp;
+  uint32_t id;
+  uint32_t entry;
+  
+  sp = (context_t *) (stack_addr + stack_size - 4 - sizeof (context_t));
+
+  id = sp->r15;
+  entry = sp->r14;
+  memset (sp, 0, sizeof (context_t));
+
+  sp->r14     = entry;
+  sp->r15     = id;
+  sp->lr      = (uint32_t) pok_arch_thread_start;
+  sp->sp      = (uint32_t) &sp->back_chain;
+  return 0;
+}
+
 #endif
Index: kernel/arch/x86/thread.c
===================================================================
--- kernel/arch/x86/thread.c	(révision 42)
+++ kernel/arch/x86/thread.c	(copie de travail)
@@ -73,4 +73,24 @@
      "ret"
      );
 
+void			pok_context_reset(uint32_t stack_size,
+					  uint32_t stack_addr)
+{
+  start_context_t* sp;
+  uint32_t id;
+  uint32_t entry;
+  
+  sp = (start_context_t *) (stack_addr + stack_size - 4 - sizeof (start_context_t));
+
+  id = sp->id;
+  entry = sp->entry;
+  memset (sp, 0, sizeof (start_context_t));
+  sp->ctx.__esp   = (uint32_t) (&sp->ctx.eip);
+  sp->ctx.eip     = (uint32_t) pok_thread_start;
+  sp->ctx.cs      = GDT_CORE_CODE_SEGMENT << 3;
+  sp->ctx.eflags  = 1 << 9;
+  sp->entry       = entry;
+  sp->id          = id;
+}
+
 #endif
Index: kernel/arch/x86/thread.h
===================================================================
--- kernel/arch/x86/thread.h	(révision 42)
+++ kernel/arch/x86/thread.h	(copie de travail)
@@ -52,6 +52,8 @@
 void			pok_context_switch(uint32_t* old_sp,
 					   uint32_t new_sp);
 
+void			pok_context_reset(uint32_t stack_size,
+					  uint32_t stack_addr);
 
 #endif /* !__POK_X86_THREAD_H__ */
 
Index: kernel/arch/sparc/thread.c
===================================================================
--- kernel/arch/sparc/thread.c	(révision 42)
+++ kernel/arch/sparc/thread.c	(copie de travail)
@@ -72,4 +72,23 @@
   pok_arch_sp = new_sp;
 }
 
+void                    pok_context_reset(uint32_t stack_size,
+                                          uint32_t stack_addr)
+{
+  (void)stack_size;
+  (void)stack_addr;
+  uint32_t id;
+  uint32_t entry;
+
+  char *ctx = (char *)(&_idlestack - 0x40);
+
+  id = *(uint32_t *)(ctx - PC_OFFSET);
+  entry =  *(uint32_t *)(ctx - I1_OFFSET);
+
+  *(uint32_t *)(ctx - RESTORE_CNT_OFFSET) = 1;
+  *(uint32_t *)(ctx - PC_OFFSET) = entry;
+  *(uint32_t *)(ctx - NPC_OFFSET) = entry + 4;
+  *(uint32_t *)(ctx - I1_OFFSET) = id;
+}
+
 #endif
Index: kernel/include/arch.h
===================================================================
--- kernel/include/arch.h	(révision 42)
+++ kernel/include/arch.h	(copie de travail)
@@ -59,6 +59,9 @@
 
 void		   pok_context_switch (uint32_t* old_sp, uint32_t new_sp);
 
+void			pok_context_reset(uint32_t stack_size,
+					  uint32_t stack_addr);
+
 pok_ret_t   pok_create_space (uint8_t partition_id, uint32_t addr, uint32_t size);
 
 uint32_t	   pok_space_base_vaddr (uint32_t addr);
Index: kernel/include/core/thread.h
===================================================================
--- kernel/include/core/thread.h	(révision 42)
+++ kernel/include/core/thread.h	(copie de travail)
@@ -73,6 +73,7 @@
 	 uint8_t		 partition;
 	 uint32_t		 sp;
 	 uint32_t    init_stack_addr;
+  uint8_t	base_priority;
 	 /* stack pointer
 		* FIXME: this is platform-dependent code, we have to handle that ! */
 } pok_thread_t;
@@ -99,6 +100,7 @@
 void           pok_thread_start (void (*entry)(), unsigned int id);
 pok_ret_t      pok_thread_suspend (void);
 pok_ret_t      pok_thread_restart (const uint32_t tid);
+pok_ret_t pok_thread_delayed_start (const uint32_t id, const uint32_t ms);
 pok_ret_t      pok_thread_get_status (const uint32_t id, pok_thread_attr_t *attr);
 pok_ret_t      pok_thread_set_priority (const uint32_t id, const uint32_t priority);
 pok_ret_t      pok_thread_resume (const uint32_t id);
Index: kernel/include/core/syscall.h
===================================================================
--- kernel/include/core/syscall.h	(révision 42)
+++ kernel/include/core/syscall.h	(copie de travail)
@@ -38,6 +38,9 @@
    POK_SYSCALL_THREAD_SET_PRIORITY								 =  60,
    POK_SYSCALL_THREAD_RESUME                       =  61,
    POK_SYSCALL_THREAD_SUSPEND_TARGET               =  62,
+   //POK_SYSCALL_THREAD_DEADLINE                     =  63,
+   //POK_SYSCALL_THREAD_STATE                        =  64,
+   POK_SYSCALL_THREAD_DELAYED_START                =  65,
 #ifdef POK_NEEDS_PORTS_SAMPLING
    POK_SYSCALL_MIDDLEWARE_SAMPLING_ID              = 101,
    POK_SYSCALL_MIDDLEWARE_SAMPLING_READ            = 102,
Index: libpok/core/threaddelayedstart.c
===================================================================
--- libpok/core/threaddelayedstart.c	(révision 0)
+++ libpok/core/threaddelayedstart.c	(révision 0)
@@ -0,0 +1,32 @@
+/*
+ *                               POK header
+ * 
+ * The following file is a part of the POK project. Any modification should
+ * made according to the POK licence. You CANNOT use this file or a part of
+ * this file is this part of a file for your own project
+ *
+ * For more information on the POK licence, please see our LICENCE FILE
+ *
+ * Please follow the coding guidelines described in doc/CODING_GUIDELINES
+ *
+ *                                      Copyright (c) 2007-2009 POK team 
+ *
+ * Created by matias on Thu May 21 23:34:13 2009 
+ */
+
+#include <core/dependencies.h>
+
+#ifdef POK_NEEDS_THREADS
+#include <arch.h>
+#include <types.h>
+#include <core/syscall.h>
+#include <core/thread.h>
+
+pok_ret_t pok_thread_delayed_start (const uint32_t thread_id, const pok_time_t ms)
+{
+   return pok_syscall2  (POK_SYSCALL_THREAD_DELAYED_START,
+                         (uint32_t)thread_id,
+                         (uint32_t)ms);
+}
+
+#endif
Index: libpok/core/Makefile
===================================================================
--- libpok/core/Makefile	(révision 42)
+++ libpok/core/Makefile	(copie de travail)
@@ -36,6 +36,7 @@
 			threadperiod.o \
 			threadsleep.o \
 			threadstatus.o \
+			threaddelayedstart.o \
 			threadid.o \
 			threadpriority.o \
 			threadresume.o
Index: libpok/arinc653/process.c
===================================================================
--- libpok/arinc653/process.c	(révision 42)
+++ libpok/arinc653/process.c	(copie de travail)
@@ -112,6 +112,12 @@
 	 strcpy(arinc_process_attribute[core_process_id].NAME, attributes->NAME);
 	 *process_id = core_process_id;
 	 *return_code = core_ret;
+   if(core_ret != POK_ERRNO_OK) {
+	   return;
+   }
+   // ARINC specifies that threads shall be created in the DORMANT state
+   core_ret = pok_thread_suspend_target(core_process_id);
+   *return_code = core_ret;
 }
 
 void STOP_SELF ()
@@ -217,22 +223,7 @@
 void START (PROCESS_ID_TYPE   process_id,
 					 RETURN_CODE_TYPE   *return_code )
 {
-	pok_thread_attr_t  attr;
-	pok_ret_t    core_ret;
-
-	core_ret = pok_thread_status (process_id, &attr);
-	if (core_ret != 0)
-		{
-			*return_code = INVALID_PARAM;
-			return ;
-		}
-	if (attr.state != DORMANT)
-		{
-			*return_code = NO_ACTION;
-			return ;
-		}
-	core_ret = pok_thread_restart(process_id);
-	*return_code = core_ret;
+	DELAYED_START(process_id,0,return_code);
 }
 
 #ifndef POK_CONFIG_OPTIMIZE_FOR_GENERATED_CODE
@@ -242,16 +233,45 @@
 	 (void) process_id;
 	 *return_code = NOT_AVAILABLE;
 }
+#endif
 
 void DELAYED_START (PROCESS_ID_TYPE   process_id,
 				SYSTEM_TIME_TYPE  delay_time,
 				RETURN_CODE_TYPE *return_code )
 {
-	 (void) process_id;
-	 (void) delay_time;
-	 *return_code = NOT_AVAILABLE;
+  pok_thread_attr_t     attr;
+  pok_ret_t		core_ret;
+
+  core_ret = pok_thread_status (process_id, &attr);
+  if (core_ret != POK_ERRNO_OK)
+    {
+      *return_code = INVALID_PARAM;
+      return;
+    }
+    if (attr.state != DORMANT)
+   {
+     *return_code = NO_ACTION;
+    return;
+   }
+  if (delay_time == INFINITE_TIME_VALUE)
+    {
+      *return_code = INVALID_PARAM;
+      return;
+    }
+  /*if ((int)attr.period != INFINITE_TIME_VALUE && delay_time >= attr.period)
+  {
+    *return_code = INVALID_PARAM;
+    return;
+  }*/
+  core_ret = pok_thread_delayed_start(process_id, delay_time);
+  if (core_ret == POK_ERRNO_OK) {
+    *return_code = NO_ERROR;
+  }else {
+    *return_code = INVALID_PARAM;
+  }
 }
 
+#ifndef POK_CONFIG_OPTIMIZE_FOR_GENERATED_CODE
 void LOCK_PREEMPTION (LOCK_LEVEL_TYPE     *lock_level,
 											RETURN_CODE_TYPE    *return_code )
 {
Index: libpok/include/core/thread.h
===================================================================
--- libpok/include/core/thread.h	(révision 42)
+++ libpok/include/core/thread.h	(copie de travail)
@@ -58,6 +58,7 @@
 pok_ret_t      pok_thread_id (uint32_t* thread_id);
 void				 pok_thread_init (void);
 pok_ret_t      pok_thread_status(const uint32_t thread_id, pok_thread_attr_t* attr);
+pok_ret_t      pok_thread_delayed_start(const uint32_t thread_id, const pok_time_t ms);
 pok_ret_t      pok_thread_set_priority(const uint32_t thread_id, const uint32_t priority);
 pok_ret_t      pok_thread_resume(const uint32_t thread_id);
 
Index: libpok/include/core/syscall.h
===================================================================
--- libpok/include/core/syscall.h	(révision 42)
+++ libpok/include/core/syscall.h	(copie de travail)
@@ -38,6 +38,9 @@
 	 POK_SYSCALL_THREAD_SET_PRIORITY								 =  60,
 	 POK_SYSCALL_THREAD_RESUME                       =  61,
 	 POK_SYSCALL_THREAD_SUSPEND_TARGET               =  62,
+   POK_SYSCALL_THREAD_DEADLINE                     =  63,
+   POK_SYSCALL_THREAD_STATE                        =  64,
+   POK_SYSCALL_THREAD_DELAYED_START		   =  65,
 #ifdef POK_NEEDS_PORTS_SAMPLING
 	 POK_SYSCALL_MIDDLEWARE_SAMPLING_ID              = 101,
 	 POK_SYSCALL_MIDDLEWARE_SAMPLING_READ            = 102,


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