From 6ccd04543c7928151d9b4fb782470e7d8f3e1e14 Mon Sep 17 00:00:00 2001 From: "bernard.xiong" Date: Mon, 1 Mar 2010 09:37:59 +0000 Subject: [PATCH] add thread example. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@456 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- examples/kernel/SConscript | 13 +++ examples/kernel/tc_comm.c | 165 ++++++++++++++++++++++++++++++ examples/kernel/tc_comm.h | 41 ++++++++ examples/kernel/thread_dynamic.c | 44 ++++++++ examples/kernel/thread_priority.c | 104 +++++++++++++++++++ examples/kernel/thread_static.c | 52 ++++++++++ 6 files changed, 419 insertions(+) create mode 100644 examples/kernel/SConscript create mode 100644 examples/kernel/tc_comm.c create mode 100644 examples/kernel/tc_comm.h create mode 100644 examples/kernel/thread_dynamic.c create mode 100644 examples/kernel/thread_priority.c create mode 100644 examples/kernel/thread_static.c diff --git a/examples/kernel/SConscript b/examples/kernel/SConscript new file mode 100644 index 0000000000..cd215ade73 --- /dev/null +++ b/examples/kernel/SConscript @@ -0,0 +1,13 @@ +Import('env') + +src_local = Split(""" +tc_comm.c +thread_static.c +thread_dynamic.c +thread_priority.c +""") + +# The set of source files associated with this SConscript file. +obj = env.Object(src_local) + +Return('obj') diff --git a/examples/kernel/tc_comm.c b/examples/kernel/tc_comm.c new file mode 100644 index 0000000000..ad0a200e88 --- /dev/null +++ b/examples/kernel/tc_comm.c @@ -0,0 +1,165 @@ +#include "tc_comm.h" +#include + +#ifdef RT_USING_TC +#define TC_PRIORITY 25 +#define TC_STACK_SIZE 0x400 + +static rt_uint8_t _tc_stat; +static struct rt_semaphore _tc_sem; +static struct rt_thread _tc_thread; +static rt_uint8_t _tc_stack[TC_STACK_SIZE]; +static char _tc_prefix[64]; +static const char* _tc_current; +static void (*_tc_cleanup)(void) = RT_NULL; + +void tc_thread_entry(void* parameter) +{ + rt_err_t result; + struct finsh_syscall* index; + + /* create tc semaphore */ + rt_sem_init(&_tc_sem, "tc", 0, RT_IPC_FLAG_FIFO); + + while (_tc_stat & TC_STAT_RUNNING) + { + for (index = _syscall_table_begin; index < _syscall_table_end; index ++) + { + /* search testcase */ + if (rt_strstr(index->name, _tc_prefix) == index->name) + { + long tick; + + _tc_current = index->name + 4; + rt_kprintf("Run TestCase: %s\n", _tc_current); + _tc_stat = TC_STAT_PASSED | TC_STAT_RUNNING; + tick = index->func(); + if (tick > 0) + { + result = rt_sem_take(&_tc_sem, tick); + if (result != RT_EOK) + rt_kprintf("TestCase[%s] failed\n", _tc_current); + else + { + if (_tc_stat & TC_STAT_FAILED) + rt_kprintf("TestCase[%s] failed\n", _tc_current); + else + rt_kprintf("TestCase[%s] passed\n", _tc_current); + } + } + + if (_tc_cleanup != RT_NULL) + { + /* perform testcase cleanup */ + _tc_cleanup(); + _tc_cleanup = RT_NULL; + } + } + } + } + + /* detach tc semaphore */ + rt_sem_detach(&_tc_sem); +} + +void tc_stop() +{ + _tc_stat &= ~TC_STAT_RUNNING; + + rt_thread_delay(RT_TICK_PER_SECOND/2); + if (_tc_thread.stat != RT_THREAD_INIT) + { + /* lock scheduler */ + rt_enter_critical(); + + /* detach old tc thread */ + rt_thread_detach(&_tc_thread); + rt_sem_detach(&_tc_sem); + + /* unlock scheduler */ + rt_exit_critical(); + } + rt_thread_delay(RT_TICK_PER_SECOND/2); +} +FINSH_FUNCTION_EXPORT(tc_stop, stop testcase thread); + +void tc_done(rt_uint8_t stat) +{ + _tc_stat |= stat; + _tc_stat &= ~TC_STAT_RUNNING; + + /* release semaphore */ + rt_sem_release(&_tc_sem); +} + +void tc_stat(rt_uint8_t stat) +{ + if (stat & TC_STAT_FAILED) + { + rt_kprintf("TestCases[%s] failed\n", _tc_current); + } + _tc_stat |= stat; +} + +void tc_cleanup(void (*cleanup)()) +{ + _tc_cleanup = cleanup; +} + +void tc_start(const char* tc_prefix) +{ + rt_err_t result; + + /* tesecase prefix is null */ + if (tc_prefix == RT_NULL) + { + rt_kprintf("TestCase Usage: tc_start(prefix)\n\n"); + rt_kprintf("list_tc() can list all testcases.\n"); + return ; + } + + /* init tc thread */ + if (_tc_stat & TC_STAT_RUNNING) + { + /* stop old tc thread */ + tc_stop(); + } + + rt_memset(_tc_prefix, 0, sizeof(_tc_prefix)); + rt_snprintf(_tc_prefix, sizeof(_tc_prefix), + "_tc_%s", tc_prefix); + + result = rt_thread_init(&_tc_thread, "tc", + tc_thread_entry, RT_NULL, + &_tc_stack[0], sizeof(_tc_stack), + TC_PRIORITY - 3, 5); + + /* set tc stat */ + _tc_stat = TC_STAT_RUNNING | TC_STAT_FAILED; + + if (result == RT_EOK) + rt_thread_startup(&_tc_thread); +} +FINSH_FUNCTION_EXPORT(tc_start, start testcase with testcase prefix or name); + +void list_tc() +{ + struct finsh_syscall* index; + + rt_kprintf("TestCases List:\n"); + for (index = _syscall_table_begin; index < _syscall_table_end; index ++) + { + /* search testcase */ + if (rt_strstr(index->name, "_tc_") == index->name) + { +#ifdef FINSH_USING_DESCRIPTION + rt_kprintf("%-16s -- %s\n", index->name + 4, index->desc); +#else + rt_kprintf("%s\n", index->name + 4); +#endif + } + } +} +FINSH_FUNCTION_EXPORT(list_tc, list all testcases); +#endif + diff --git a/examples/kernel/tc_comm.h b/examples/kernel/tc_comm.h new file mode 100644 index 0000000000..9f96d24e09 --- /dev/null +++ b/examples/kernel/tc_comm.h @@ -0,0 +1,41 @@ +#ifndef __TC_COMM_H__ +#define __TC_COMM_H__ + +/* + * RT-Thread TestCase + * + */ +#include +#include + +#if RT_THREAD_PRIORITY_MAX == 8 +#define THREAD_PRIORITY 6 +#elif RT_THREAD_PRIORITY_MAX == 32 +#define THREAD_PRIORITY 25 +#elif RT_THREAD_PRIORITY_MAX == 256 +#define THREAD_PRIORITY 200 +#endif +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +#define TC_STAT_END 0x00 +#define TC_STAT_RUNNING 0x01 +#define TC_STAT_FAILED 0x10 +#define TC_STAT_PASSED 0x00 + +#ifdef RT_USING_TC +void tc_start(const char* tc_prefix); +void tc_stop(void); +void tc_done(rt_uint8_t state); +void tc_stat(rt_uint8_t state); +void tc_cleanup(void (*cleanup)(void)); +#else +#define tc_start(x) +#define tc_stop() +#define tc_done(s) +#define tc_stat(s) +#define tc_cleanup(c) +#endif + +#endif + diff --git a/examples/kernel/thread_dynamic.c b/examples/kernel/thread_dynamic.c new file mode 100644 index 0000000000..9d1218be5d --- /dev/null +++ b/examples/kernel/thread_dynamic.c @@ -0,0 +1,44 @@ +#include +#include "tc_comm.h" + +static void thread_entry(void* parameter) +{ + rt_kprintf("thread dynamicly created ok\n"); + rt_thread_delay(10); + rt_kprintf("thread exit\n"); + + tc_done(TC_STAT_PASSED); +} + +int thread_dynamic_init() +{ + rt_thread_t tid; + + tid = rt_thread_create("test", + thread_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid != RT_NULL) + rt_thread_startup(tid); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + return 0; +} + +#ifdef RT_USING_TC +int _tc_thread_dynamic() +{ + thread_dynamic_init(); + + return 20; +} +FINSH_FUNCTION_EXPORT(_tc_thread_dynamic, a dynamic thread test); +#else +int rt_application_init() +{ + thread_dynamic_init(); + + return 0; +} +#endif + diff --git a/examples/kernel/thread_priority.c b/examples/kernel/thread_priority.c new file mode 100644 index 0000000000..7864a91232 --- /dev/null +++ b/examples/kernel/thread_priority.c @@ -0,0 +1,104 @@ +#include +#include "tc_comm.h" + +struct rt_thread thread1; +struct rt_thread thread2; +static char thread1_stack[THREAD_STACK_SIZE]; +static char thread2_stack[THREAD_STACK_SIZE]; +static rt_uint32_t count = 0; + +/* + * the priority of thread1 > the priority of thread2 + */ +void thread1_entry(void* parameter) +{ + while (1) + { + count ++; + rt_kprintf("count = %d\n", count); + + rt_thread_delay(10); + } +} + +void thread2_entry(void* parameter) +{ + rt_tick_t tick; + + tick = rt_tick_get(); + while (1) + { + if (rt_tick_get() - tick >= 100) + { + if (count == 0) + tc_done(TC_STAT_FAILED); + else + tc_done(TC_STAT_PASSED); + + break; + } + } +} + +int thread_priority_init() +{ + rt_err_t result; + + result = rt_thread_init(&thread1, + "t1", + thread1_entry, RT_NULL, + &thread1_stack[0], sizeof(thread1_stack), + THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (result == RT_EOK) + rt_thread_startup(&thread1); + else + tc_stat(TC_STAT_FAILED); + + rt_thread_init(&thread2, + "t2", + thread2_entry, RT_NULL, + &thread2_stack[0], sizeof(thread2_stack), + THREAD_PRIORITY + 1, THREAD_TIMESLICE); + + if (result == RT_EOK) + rt_thread_startup(&thread2); + else + tc_stat(TC_STAT_FAILED); + + return 0; +} + +#ifdef RT_USING_TC +static void _tc_cleanup() +{ + /* lock scheduler */ + rt_enter_critical(); + + if (thread1.stat != RT_THREAD_CLOSE) + rt_thread_detach(&thread1); + if (thread2.stat != RT_THREAD_CLOSE) + rt_thread_detach(&thread2); + + /* unlock scheduler */ + rt_exit_critical(); +} +int _tc_thread_priority() +{ + count = 0; + + /* set tc cleanup */ + tc_cleanup(_tc_cleanup); + thread_priority_init(); + + return RT_TICK_PER_SECOND; +} +FINSH_FUNCTION_EXPORT(_tc_thread_priority, a priority thread test); +#else +int rt_application_init() +{ + thread_priority_init(); + + return 0; +} +#endif + diff --git a/examples/kernel/thread_static.c b/examples/kernel/thread_static.c new file mode 100644 index 0000000000..9a8c158c86 --- /dev/null +++ b/examples/kernel/thread_static.c @@ -0,0 +1,52 @@ +#include +#include "tc_comm.h" + +/* + * This is an example for static thread + */ +static struct rt_thread thread; +static char thread_stack[THREAD_STACK_SIZE]; +static void thread_entry(void* parameter) +{ + rt_kprintf("thread staticly inited ok\n"); + rt_thread_delay(10); + rt_kprintf("thread exit\n"); + + tc_done(TC_STAT_PASSED); +} + +rt_err_t thread_static_init() +{ + rt_err_t result; + + result = rt_thread_init(&thread, + "test", + thread_entry, RT_NULL, + &thread_stack[0], sizeof(thread_stack), + THREAD_PRIORITY, 10); + + if (result == RT_EOK) + rt_thread_startup(&thread); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + return result; +} + +#ifdef RT_USING_TC +int _tc_thread_static() +{ + thread_static_init(); + + return 20; +} +FINSH_FUNCTION_EXPORT(_tc_thread_static, a static thread test); +#else +int rt_application_init() +{ + thread_static_init(); + + return 0; +} +#endif +