[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,