diff --git a/examples/kernel/SConscript b/examples/kernel/SConscript index 30da9421ab..1020d7dfef 100644 --- a/examples/kernel/SConscript +++ b/examples/kernel/SConscript @@ -9,6 +9,10 @@ thread_same_priority.c thread_static_simple.c thread_dynamic_simple.c thread_delete.c +thread_detach.c +thread_yield.c +thread_suspend.c +thread_resume.c semaphore_static.c semaphore_dynamic.c semaphore_priority.c diff --git a/examples/kernel/thread_delete.c b/examples/kernel/thread_delete.c index cd632815c4..0cd62390c5 100644 --- a/examples/kernel/thread_delete.c +++ b/examples/kernel/thread_delete.c @@ -1,43 +1,72 @@ +/* + * 程序清单:删除线程 + * + * 这个例子会创建两个线程,在其中一个线程中删除另外一个线程。 + */ #include #include "tc_comm.h" /* - * This is an example for dynamic thread + * 线程删除(rt_thread_delete)函数仅适合于动态线程,为了在一个线程 + * 中访问另一个线程的控制块,所以把线程块指针声明成全局类型以供全 + * 局访问 */ static rt_thread_t tid1 = RT_NULL, tid2 = RT_NULL; +/* 线程1的入口函数 */ static void thread1_entry(void* parameter) { rt_uint32_t count = 0; while (1) { + /* 线程1采用低优先级运行,一直打印计数值 */ rt_kprintf("thread count: %d\n", count ++); } } +/* 线程2的入口函数 */ static void thread2_entry(void* parameter) { + /* 线程2拥有较高的优先级,以抢占线程1而获得执行 */ + + /* 线程2启动后先睡眠10个OS Tick */ rt_thread_delay(10); + + /* + * 线程2唤醒后直接删除线程1,删除线程1后,线程1自动脱离就绪线程 + * 队列 + */ rt_thread_delete(tid1); - /* delay thread2 to switch to idle thread */ + /* + * 线程2继续休眠10个OS Tick然后退出,线程2休眠后应切换到idle线程 + * idle线程将执行真正的线程1控制块和线程栈的删除 + */ rt_thread_delay(10); + + /* + * 线程2运行结束后也将自动被删除(线程控制块和线程栈依然在idle线 + * 程中释放) + */ } +/* 线程删除示例的初始化 */ int thread_delete_init() { - tid1 = rt_thread_create("t1", - thread1_entry, (void*)1, + /* 创建线程1 */ + tid1 = rt_thread_create("t1", /* 线程1的名称是t1 */ + thread1_entry, RT_NULL, /* 入口时thread1_entry,参数是RT_NULL */ THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); - if (tid1 != RT_NULL) + if (tid1 != RT_NULL) /* 如果获得线程控制块,启动这个线程 */ rt_thread_startup(tid1); else tc_stat(TC_STAT_END | TC_STAT_FAILED); - tid2 = rt_thread_create("t2", - thread2_entry, (void*)2, + /* 创建线程1 */ + tid2 = rt_thread_create("t2", /* 线程1的名称是t2 */ + thread2_entry, RT_NULL, /* 入口时thread2_entry,参数是RT_NULL */ THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); - if (tid2 != RT_NULL) + if (tid2 != RT_NULL) /* 如果获得线程控制块,启动这个线程 */ rt_thread_startup(tid2); else tc_stat(TC_STAT_END | TC_STAT_FAILED); diff --git a/examples/kernel/thread_detach.c b/examples/kernel/thread_detach.c new file mode 100644 index 0000000000..2cb8227df5 --- /dev/null +++ b/examples/kernel/thread_detach.c @@ -0,0 +1,118 @@ +/* + * 程序清单:线程脱离 + * + * 这个例子会创建两个线程,在其中一个线程中执行对另一个线程的脱离。 + */ +#include +#include "tc_comm.h" + +/* 线程1控制块 */ +static struct rt_thread thread1; +/* 线程1栈 */ +static rt_uint8_t thread1_stack[THREAD_STACK_SIZE]; +/* 线程2控制块 */ +static struct rt_thread thread2; +/* 线程2栈 */ +static rt_uint8_t thread2_stack[THREAD_STACK_SIZE]; + +/* 线程1入口 */ +static void thread1_entry(void* parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + /* 线程1采用低优先级运行,一直打印计数值 */ + rt_kprintf("thread count: %d\n", count ++); + } +} + +/* 线程2入口 */ +static void thread2_entry(void* parameter) +{ + /* 线程2拥有较高的优先级,以抢占线程1而获得执行 */ + + /* 线程2启动后先睡眠10个OS Tick */ + rt_thread_delay(10); + + /* + * 线程2唤醒后直接执行线程1脱离,线程1将从就绪线程队列中删除 + */ + rt_thread_detach(&thread1); + + /* + * 线程2继续休眠10个OS Tick然后退出 + */ + rt_thread_delay(10); + + /* + * 线程2运行结束后也将自动被从就绪队列中删除,并脱离线程队列 + */ +} + +int thread_detach_init() +{ + rt_err_t result; + + /* 初始化线程1 */ + result = rt_thread_init(&thread1, "t1", /* 线程名:t1 */ + thread1_entry, RT_NULL, /* 线程的入口是thread1_entry,入口参数是RT_NULL*/ + &thread1_stack[0], sizeof(thread1_stack), /* 线程栈是thread1_stack */ + THREAD_PRIORITY, 10); + if (result == RT_EOK) /* 如果返回正确,启动线程1 */ + rt_thread_startup(&thread1); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + /* 初始化线程2 */ + result = rt_thread_init(&thread2, "t2", /* 线程名:t2 */ + thread2_entry, RT_NULL, /* 线程的入口是thread2_entry,入口参数是RT_NULL*/ + &thread2_stack[0], sizeof(thread2_stack), /* 线程栈是thread2_stack */ + THREAD_PRIORITY - 1, 10); + if (result == RT_EOK) /* 如果返回正确,启动线程2 */ + rt_thread_startup(&thread2); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + return 0; +} + +#ifdef RT_USING_TC +static void _tc_cleanup() +{ + /* 调度器上锁,上锁后,将不再切换到其他线程,仅响应中断 */ + rt_enter_critical(); + + /* 执行线程脱离 */ + if (thread1.stat != RT_THREAD_CLOSE) + rt_thread_detach(&thread1); + if (thread2.stat != RT_THREAD_CLOSE) + rt_thread_detach(&thread2); + + /* 调度器解锁 */ + rt_exit_critical(); + + /* 设置TestCase状态 */ + tc_done(TC_STAT_PASSED); +} + +int _tc_thread_detach() +{ + /* 设置TestCase清理回调函数 */ + tc_cleanup(_tc_cleanup); + thread_detach_init(); + + /* 返回TestCase运行的最长时间 */ + return 100; +} +/* 输出函数命令到finsh shell中 */ +FINSH_FUNCTION_EXPORT(_tc_thread_detach, a static thread example); +#else +/* 用户应用入口 */ +int rt_application_init() +{ + thread_detach_init(); + + return 0; +} +#endif diff --git a/examples/kernel/thread_dynamic_simple.c b/examples/kernel/thread_dynamic_simple.c index 9f822eefc7..e7f3dfb61b 100644 --- a/examples/kernel/thread_dynamic_simple.c +++ b/examples/kernel/thread_dynamic_simple.c @@ -1,35 +1,45 @@ +/* + * 程序清单:动态线程 + * + * 这个程序会初始化2个动态线程,它们拥有共同的入口函数,但参数不相同 + */ #include #include "tc_comm.h" -/* - * This is an example for dynamic thread - */ -static rt_thread_t tid1 = RT_NULL, tid2 = RT_NULL; +/* 指向线程控制块的指针 */ +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +/* 线程入口 */ static void thread_entry(void* parameter) { rt_uint32_t count = 0; - rt_uint32_t no = (rt_uint32_t) parameter; + rt_uint32_t no = (rt_uint32_t) parameter; /* 获得正确的入口参数 */ while (1) { + /* 打印线程计数值输出 */ rt_kprintf("thread%d count: %d\n", no, count ++); + + /* 休眠10个OS Tick */ rt_thread_delay(10); } } int thread_dynamic_simple_init() { - tid1 = rt_thread_create("t1", - thread_entry, (void*)1, + /* 创建线程1 */ + tid1 = rt_thread_create("thread", + thread_entry, RT_NULL, /* 线程入口是thread1_entry, 入口参数是RT_NULL */ THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid1 != RT_NULL) rt_thread_startup(tid1); else tc_stat(TC_STAT_END | TC_STAT_FAILED); - tid2 = rt_thread_create("t2", - thread_entry, (void*)2, - THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE); + /* 创建线程2 */ + tid2 = rt_thread_create("thread", + thread_entry, RT_NULL, /* 线程入口是thread2_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid2 != RT_NULL) rt_thread_startup(tid2); else @@ -41,31 +51,35 @@ int thread_dynamic_simple_init() #ifdef RT_USING_TC static void _tc_cleanup() { - /* lock scheduler */ + /* 调度器上锁,上锁后,将不再切换到其他线程,仅响应中断 */ rt_enter_critical(); - /* delete thread */ + /* 删除线程 */ if (tid1 != RT_NULL && tid1->stat != RT_THREAD_CLOSE) rt_thread_delete(tid1); if (tid2 != RT_NULL && tid2->stat != RT_THREAD_CLOSE) rt_thread_delete(tid2); - /* unlock scheduler */ + /* 调度器解锁 */ rt_exit_critical(); + /* 设置TestCase状态 */ tc_done(TC_STAT_PASSED); } int _tc_thread_dynamic_simple() { - /* set tc cleanup */ + /* 设置TestCase清理回调函数 */ tc_cleanup(_tc_cleanup); thread_dynamic_simple_init(); + /* 返回TestCase运行的最长时间 */ return 100; } +/* 输出函数命令到finsh shell中 */ FINSH_FUNCTION_EXPORT(_tc_thread_dynamic_simple, a dynamic thread example); #else +/* 用户应用入口 */ int rt_application_init() { thread_dynamic_simple_init(); diff --git a/examples/kernel/thread_resume.c b/examples/kernel/thread_resume.c new file mode 100644 index 0000000000..23dfcdc132 --- /dev/null +++ b/examples/kernel/thread_resume.c @@ -0,0 +1,105 @@ +/* + * 程序清单:唤醒线程 + * + * 这个例子中将创建两个动态线程,低优先级线程将挂起自身,然后 + * 高优先级线程将在一定时刻后唤醒低优先级线程。 + */ +#include +#include "tc_comm.h" + +/* 指向线程控制块的指针 */ +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +/* 线程1入口 */ +static void thread1_entry(void* parameter) +{ + /* 低优先级线程1开始运行 */ + rt_kprintf("thread1 startup%d\n"); + + /* 挂起自身 */ + rt_kprintf("suspend thread self\n"); + rt_thread_suspend(tid1); + /* 主动执行线程调度 */ + rt_schedule(); + + /* 当线程1被唤醒时 */ + rt_kprintf("thread1 resumed\n"); +} + +/* 线程2入口 */ +static void thread2_entry(void* parameter) +{ + /* 延时10个OS Tick */ + rt_thread_delay(10); + + /* 唤醒线程1 */ + rt_thread_resume(tid1); + + /* 延时10个OS Tick */ + rt_thread_delay(10); + + /* 线程2自动退出 */ +} + +int thread_resume_init() +{ + /* 创建线程1 */ + tid1 = rt_thread_create("thread", + thread1_entry, RT_NULL, /* 线程入口是thread1_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + /* 创建线程2 */ + tid2 = rt_thread_create("thread", + thread2_entry, RT_NULL, /* 线程入口是thread2_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + return 0; +} + +#ifdef RT_USING_TC +static void _tc_cleanup() +{ + /* 调度器上锁,上锁后,将不再切换到其他线程,仅响应中断 */ + rt_enter_critical(); + + /* 删除线程 */ + if (tid1 != RT_NULL && tid1->stat != RT_THREAD_CLOSE) + rt_thread_delete(tid1); + if (tid2 != RT_NULL && tid2->stat != RT_THREAD_CLOSE) + rt_thread_delete(tid2); + + /* 调度器解锁 */ + rt_exit_critical(); + + /* 设置TestCase状态 */ + tc_done(TC_STAT_PASSED); +} + +int _tc_thread_resume() +{ + /* 设置TestCase清理回调函数 */ + tc_cleanup(_tc_cleanup); + thread_resume_init(); + + /* 返回TestCase运行的最长时间 */ + return 100; +} +/* 输出函数命令到finsh shell中 */ +FINSH_FUNCTION_EXPORT(_tc_thread_resume, a thread resume example); +#else +/* 用户应用入口 */ +int rt_application_init() +{ + thread_resume_init(); + + return 0; +} +#endif diff --git a/examples/kernel/thread_static_simple.c b/examples/kernel/thread_static_simple.c index 24514c1a5e..61005fd23b 100644 --- a/examples/kernel/thread_static_simple.c +++ b/examples/kernel/thread_static_simple.c @@ -1,78 +1,95 @@ +/* + * 程序清单:静态线程 + * + * 这个程序会初始化2个静态线程,它们拥有共同的入口函数,但参数不相同 + */ #include #include "tc_comm.h" -/* - * This is an example for static thread - */ +/* 线程1控制块 */ static struct rt_thread thread1; +/* 线程1栈 */ +static rt_uint8_t thread1_stack[THREAD_STACK_SIZE]; +/* 线程2控制块 */ static struct rt_thread thread2; -static char thread1_stack[THREAD_STACK_SIZE]; -static char thread2_stack[THREAD_STACK_SIZE]; +/* 线程2栈 */ +static rt_uint8_t thread2_stack[THREAD_STACK_SIZE]; +/* 线程入口 */ static void thread_entry(void* parameter) { rt_uint32_t count = 0; - rt_uint32_t no = (rt_uint32_t) parameter; + rt_uint32_t no = (rt_uint32_t) parameter; /* 获得正确的入口参数 */ while (1) { + /* 打印线程计数值输出 */ rt_kprintf("thread%d count: %d\n", no, count ++); + + /* 休眠10个OS Tick */ rt_thread_delay(10); } } -rt_err_t thread_static_simple_init() +int thread_static_simple_init() { rt_err_t result; - result = rt_thread_init(&thread1, - "t1", - thread_entry, (void*)1, - &thread1_stack[0], sizeof(thread1_stack), + /* 初始化线程1 */ + result = rt_thread_init(&thread1, "t1", /* 线程名:t1 */ + thread_entry, (void*)1, /* 线程的入口是thread_entry,入口参数是1 */ + &thread1_stack[0], sizeof(thread1_stack), /* 线程栈是thread1_stack */ THREAD_PRIORITY, 10); - if (result == RT_EOK) + if (result == RT_EOK) /* 如果返回正确,启动线程1 */ rt_thread_startup(&thread1); else tc_stat(TC_STAT_END | TC_STAT_FAILED); - result = rt_thread_init(&thread2, - "t2", - thread_entry, (void*)2, - &thread2_stack[0], sizeof(thread2_stack), + /* 初始化线程2 */ + result = rt_thread_init(&thread2, "t2", /* 线程名:t2 */ + thread_entry, RT_NULL, /* 线程的入口是thread_entry,入口参数是2 */ + &thread2_stack[0], sizeof(thread2_stack), /* 线程栈是thread2_stack */ THREAD_PRIORITY + 1, 10); - if (result == RT_EOK) + if (result == RT_EOK) /* 如果返回正确,启动线程2 */ rt_thread_startup(&thread2); else tc_stat(TC_STAT_END | TC_STAT_FAILED); - return result; + 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(); + + /* 设置TestCase状态 */ + tc_done(TC_STAT_PASSED); } int _tc_thread_static_simple() { - /* set tc cleanup */ + /* 设置TestCase清理回调函数 */ tc_cleanup(_tc_cleanup); thread_static_simple_init(); - return 20; + /* 返回TestCase运行的最长时间 */ + return 100; } +/* 输出函数命令到finsh shell中 */ FINSH_FUNCTION_EXPORT(_tc_thread_static_simple, a static thread example); #else +/* 用户应用入口 */ int rt_application_init() { thread_static_simple_init(); @@ -80,4 +97,3 @@ int rt_application_init() return 0; } #endif - diff --git a/examples/kernel/thread_suspend.c b/examples/kernel/thread_suspend.c new file mode 100644 index 0000000000..2be237a2a5 --- /dev/null +++ b/examples/kernel/thread_suspend.c @@ -0,0 +1,100 @@ +/* + * 程序清单:挂起线程 + * + * 这个例子中将创建两个动态线程,高优先级线程将在一定时刻后挂起低优先级线程。 + */ +#include +#include "tc_comm.h" + +/* 指向线程控制块的指针 */ +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +/* 线程1入口 */ +static void thread1_entry(void* parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + /* 线程1采用低优先级运行,一直打印计数值 */ + rt_kprintf("thread count: %d\n", count ++); + } +} + +/* 线程2入口 */ +static void thread2_entry(void* parameter) +{ + /* 延时10个OS Tick */ + rt_thread_delay(10); + + /* 挂起线程1 */ + rt_thread_suspend(tid1); + + /* 延时10个OS Tick */ + rt_thread_delay(10); + + /* 线程2自动退出 */ +} + +int thread_suspend_init() +{ + /* 创建线程1 */ + tid1 = rt_thread_create("thread", + thread1_entry, RT_NULL, /* 线程入口是thread1_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + /* 创建线程2 */ + tid2 = rt_thread_create("thread", + thread2_entry, RT_NULL, /* 线程入口是thread2_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + return 0; +} + +#ifdef RT_USING_TC +static void _tc_cleanup() +{ + /* 调度器上锁,上锁后,将不再切换到其他线程,仅响应中断 */ + rt_enter_critical(); + + /* 删除线程 */ + if (tid1 != RT_NULL && tid1->stat != RT_THREAD_CLOSE) + rt_thread_delete(tid1); + if (tid2 != RT_NULL && tid2->stat != RT_THREAD_CLOSE) + rt_thread_delete(tid2); + + /* 调度器解锁 */ + rt_exit_critical(); + + /* 设置TestCase状态 */ + tc_done(TC_STAT_PASSED); +} + +int _tc_thread_suspend() +{ + /* 设置TestCase清理回调函数 */ + tc_cleanup(_tc_cleanup); + thread_suspend_init(); + + /* 返回TestCase运行的最长时间 */ + return 100; +} +/* 输出函数命令到finsh shell中 */ +FINSH_FUNCTION_EXPORT(_tc_thread_suspend, a thread suspend example); +#else +/* 用户应用入口 */ +int rt_application_init() +{ + thread_suspend_init(); + + return 0; +} +#endif diff --git a/examples/kernel/thread_yield.c b/examples/kernel/thread_yield.c new file mode 100644 index 0000000000..e9fb7f57f9 --- /dev/null +++ b/examples/kernel/thread_yield.c @@ -0,0 +1,101 @@ +/* + * 程序清单: + */ +#include +#include "tc_comm.h" + +/* 指向线程控制块的指针 */ +static rt_thread_t tid1 = RT_NULL; +static rt_thread_t tid2 = RT_NULL; +/* 线程1入口 */ +static void thread1_entry(void* parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + /* 打印线程1的输出 */ + rt_kprintf("thread1: count = %d\n", count ++); + + /* 执行yield后应该切换到thread2执行 */ + rt_thread_yield(); + } +} + +/* 线程2入口 */ +static void thread2_entry(void* parameter) +{ + rt_uint32_t count = 0; + + while (1) + { + /* 打印线程2的输出 */ + rt_kprintf("thread2: count = %d\n", count ++); + + /* 执行yield后应该切换到thread1执行 */ + rt_thread_yield(); + } +} + +int thread_yield_init() +{ + /* 创建线程1 */ + tid1 = rt_thread_create("thread", + thread1_entry, RT_NULL, /* 线程入口是thread1_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + /* 创建线程2 */ + tid2 = rt_thread_create("thread", + thread2_entry, RT_NULL, /* 线程入口是thread2_entry, 入口参数是RT_NULL */ + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + else + tc_stat(TC_STAT_END | TC_STAT_FAILED); + + return 0; +} + +#ifdef RT_USING_TC +static void _tc_cleanup() +{ + /* 调度器上锁,上锁后,将不再切换到其他线程,仅响应中断 */ + rt_enter_critical(); + + /* 删除线程 */ + if (tid1 != RT_NULL && tid1->stat != RT_THREAD_CLOSE) + rt_thread_delete(tid1); + if (tid2 != RT_NULL && tid2->stat != RT_THREAD_CLOSE) + rt_thread_delete(tid2); + + /* 调度器解锁 */ + rt_exit_critical(); + + /* 设置TestCase状态 */ + tc_done(TC_STAT_PASSED); +} + +int _tc_thread_yield() +{ + /* 设置TestCase清理回调函数 */ + tc_cleanup(_tc_cleanup); + thread_yield_init(); + + /* 返回TestCase运行的最长时间 */ + return 100; +} +/* 输出函数命令到finsh shell中 */ +FINSH_FUNCTION_EXPORT(_tc_thread_yield, a thread yield example); +#else +/* 用户应用入口 */ +int rt_application_init() +{ + thread_yield_init(); + + return 0; +} +#endif