嵌入式操作系统内核原理和开发(线程状态)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
软件英才网软件行业驰名招聘网站嵌入式操作系统内核原理和开发(线程状态)
从第一篇的os博客以来,谈了很多内容,有中断、切换、调度、内存、互斥和延时等等,
但是线程的状态却没有涉及到,今天我们要好好说一说。
说到线程的状态,按照一般的说法,主要包括就绪、延时、阻塞、阻塞超时四个状态。
如果线程没有死亡的话,那么这几个状态
也够用了,但是我们后来发现可能需要对某些线程进行挂起处理,这可能是出现了故障或者
是为了调试使用。
因此,除了上面的四个状态,我们还要补充对应的四个挂起状态,分别是
挂起、延时挂起、阻塞挂起、阻塞延时挂起。
说到了线程状态,下面我们就看看常见的线程处理函数有哪些,无外乎线程创建、线
程延时、线程挂起、线程恢复和线程删除等等。
1RAW_U16 raw_task_create(RAW_TASK_OBJ *task_obj, RAW_U8 *task_name, RAW_VOID *task_arg,
2 RAW_U8 task_prio, RAW_U16 time_slice,
PORT_STACK *task_stack_base,
3 RAW_U32 stack_size, RAW_TASK_ENTRY task_entry,
RAW_U8 auto_start)
4
5 {
6 #if (RAW_TASK_STACK_CHECK > 0)
7 PORT_STACK *p_stack;
8 RAW_U32 i;
9 #endif
10
11 RAW_SR_ALLOC();
12
13 #if (RAW_TASK_FUNCTION_CHECK > 0)
14
15if (task_obj == 0) {
16return RAW_NULL_OBJECT;
17 }
18
19if (task_prio >= CONFIG_RAW_PRIO_MAX) {
20return RAW_BYOND_MAX_PRIORITY;
21 }
22
23if (task_stack_base == 0) {
24return RAW_NULL_POINTER;
软件英才网软件行业驰名招聘网站25 }
26
27if (task_entry == 0) {
28return RAW_NULL_POINTER;
29 }
30
31 #endif
32
33 RAW_CRITICAL_ENTER();
34
35if (task_prio == IDLE_PRIORITY) {
36
37if (idle_task_exit) {
38
39 RAW_CRITICAL_EXIT();
40return RAW_IDLE_EXIT;
41
42 }
43
44 idle_task_exit = 1;
45 }
46
47
48 RAW_CRITICAL_EXIT();
49
50 raw_memset(task_obj, 0, sizeof(RAW_TASK_OBJ));
51
52 #if (CONFIG_ROUND_ROBIN > 0)
53
54if (time_slice) {
55 task_obj->time_total = time_slice;
56
57 }
58
59else {
60
61 task_obj->time_total = TIME_SLICE_DEFAULT;
62 }
63
64 task_obj->time_slice = task_obj->time_total;
65
66 #endif
软件英才网软件行业驰名招聘网站68if (auto_start)
69 task_obj->task_state = RAW_RDY;
70else
71 task_obj->task_state = RAW_SUSPENDED;
72
73
74 #if (RAW_TASK_STACK_CHECK > 0)
75
76 task_obj->task_stack_base = task_stack_base;
77 p_stack = task_stack_base;
78
79for (i = 0; i < stack_size; i++) {
80 *p_stack++ =0;
81
82 }
83
84 #endif
85
86 task_obj->task_stack = port_stack_init(task_stack_base, stack_size, task_arg, task_entry);
87 task_obj->task_name = task_name;
88 task_obj->priority = task_prio;
89
90 task_create_hook(task_obj);
91
92
93 RAW_CRITICAL_ENTER();
94
95 #if (RAW_TASK_STACK_CHECK > 0)
96 task_obj->stack_size = stack_size;
97 list_insert(&task_head, &task_obj->stack_check_list);
98 #endif
99
100if (auto_start) {
101 add_ready_list_end(&raw_ready_queue, task_obj);
102 }
103
104if (raw_os_active != RAW_OS_RUNNING) { /* Return if multitasking has not started */
105 RAW_CRITICAL_EXIT();
106return RAW_OS_STOPPED;
107 }
软件英才网软件行业驰名招聘网站109 RAW_CRITICAL_EXIT();
110
111if (auto_start) {
112 raw_sched();
113 }
114
115return RAW_SUCCESS;
116
117 }
118
创建线程的函数是比较复杂的,内容长一些,参数也多一些。
首先看看有哪些参数,虽然很多,但是慢慢梳理一下也不难理解,有名称、参数、优先级、时间片、堆栈起始指针、堆栈大小、入口函数和标志。
整个函数基本上都是赋值的过程,最重要的其实就两个部分,一个是port_stack_init,另一个就是add_ready_list_end。
前者可以对堆栈进行默认处理,比如压入一些寄存器、压入函数参数、函数指针等等,后者就是把线程加入到就绪队列。
119RAW_U16 raw_sleep(RAW_U32 dly)
120 {
121 RAW_U16 error_status;
122
123 RAW_SR_ALLOC();
124
125 #if (RAW_TASK_FUNCTION_CHECK > 0)
126
127if (raw_int_nesting) {
128
129return RAW_NOT_CALLED_BY_ISR;
130 }
131 #endif
132
133 RAW_CRITICAL_ENTER();
134
135if (dly) {
136
137/*system is locked so task can not sleep just return immediately*/ 138if (raw_sched_lock) {
139 RAW_CRITICAL_EXIT();
140return RAW_SCHED_DISABLE;
141 }
142
143 raw_task_active->task_state = RAW_DLY;
软件英才网软件行业驰名招聘网站144
145 tick_list_insert(raw_task_active, dly);
146
147 remove_ready_list(&raw_ready_queue, raw_task_active);
148 }
149
150else {
151/*make current task to the end of ready list*/
152 move_to_ready_list_end(&raw_ready_queue, raw_task_active); 153 }
154
155 RAW_CRITICAL_EXIT();
156
157 raw_sched();
158
159if (dly) {
160/*task is timeout after sleep*/
161 error_status = block_state_post_process(raw_task_active, 0); 162 }
163
164else {
165
166 error_status = RAW_SUCCESS;
167
168 }
169
170return error_status;
171 }
172
173RAW_U16 raw_task_suspend(RAW_TASK_OBJ *task_ptr)
174 {
175 RAW_SR_ALLOC();
176
177 #if (RAW_TASK_FUNCTION_CHECK > 0)
178
179if (task_ptr == 0) {
180return RAW_NULL_OBJECT;
181 }
182
183 #endif
软件英才网软件行业驰名招聘网站184
185if (task_ptr->priority == IDLE_PRIORITY) {
186return RAW_SUSPEND_TASK_NOT_ALLOWED;
187 }
188
189 RAW_CRITICAL_ENTER();
190
191if (task_ptr == raw_task_active) {
192
193if (raw_sched_lock) {
194 RAW_CRITICAL_EXIT();
195return RAW_SCHED_LOCKED;
196 }
197 }
198
199switch (task_ptr->task_state) {
200case RAW_RDY:
201 task_ptr->task_state = RAW_SUSPENDED;
202 remove_ready_list(&raw_ready_queue, task_ptr);
203break;
204
205case RAW_DLY:
206 task_ptr->task_state = RAW_DLY_SUSPENDED;
207break;
208
209case RAW_PEND:
210
211 task_ptr->task_state = RAW_PEND_SUSPENDED;
212break;
213
214
215case RAW_PEND_TIMEOUT:
216 task_ptr->task_state = RAW_PEND_TIMEOUT_SUSPENDED;
217break;
218
219
220case RAW_DLY_SUSPENDED:
221case RAW_PEND_SUSPENDED:
222case RAW_PEND_TIMEOUT_SUSPENDED:
223 RAW_CRITICAL_EXIT();
224return RAW_SUSPENDED_AGAIN;
225
软件英才网软件行业驰名招聘网站227default:
228
229 #if (CONFIG_RAW_ASSERT > 0)
230 RAW_ASSERT(0);
231 #endif
232
233 RAW_CRITICAL_EXIT();
234return RAW_STATE_UNKNOWN;
235 }
236
237 RAW_CRITICAL_EXIT();
238
239 raw_sched();
240
241return RAW_SUCCESS;
242 }
243
挂起任务的动作其实是比较残暴的,因为此时你不知道线程处于什么状态。
当然任务如果已经被挂起了,那什么也不用做了,否则就需要把任务修改为对应的挂起状态就可以了。
当然如果任务是就绪态的,还得把任务清除处理来。
在函数结束的时候,我们需要重新进行调度,因为很有可能当前最高优先级的线程已经发生了改变。
244RAW_U16 raw_task_resume(RAW_TASK_OBJ *task_ptr)
245 {
246 RAW_SR_ALLOC();
247
248 #if (RAW_TASK_FUNCTION_CHECK > 0)
249
250if (task_ptr == 0) {
251return RAW_NULL_OBJECT;
252 }
253
254 #endif
255
256 RAW_CRITICAL_ENTER();
257
258switch (task_ptr->task_state) {
259case RAW_RDY:
260case RAW_DLY:
261case RAW_PEND:
262case RAW_PEND_TIMEOUT:
软件英才网软件行业驰名招聘网站263
264 RAW_CRITICAL_EXIT();
265return HAS_NOT_SUSPENDED;
266
267
268case RAW_SUSPENDED:
269 task_ptr->task_state = RAW_RDY;
270 add_ready_list(&raw_ready_queue, task_ptr);
271break;
272
273case RAW_DLY_SUSPENDED:
274
275 task_ptr->task_state = RAW_DLY;
276break;
277
278case RAW_PEND_SUSPENDED:
279
280 task_ptr->task_state = RAW_PEND;
281break;
282
283case RAW_PEND_TIMEOUT_SUSPENDED:
284
285 task_ptr->task_state = RAW_PEND_TIMEOUT;
286break;
287
288default:
289
290 #if (CONFIG_RAW_ASSERT > 0)
291 RAW_ASSERT(0);
292 #endif
293
294 RAW_CRITICAL_EXIT();
295
296return RAW_STATE_UNKNOWN;
297
298 }
299
300 RAW_CRITICAL_EXIT();
301
302 raw_sched();
303
304return RAW_SUCCESS;
软件英才网软件行业驰名招聘网站306
恢复函数其实就是挂起函数的逆向操作。
如果任务没有被挂起,那么什么也不用做。
否则就需要把任务的状态修改为对应的非挂起状态,当然该就绪的线程还得加入到就绪队列当中去。
同时在函数结束之前不忘调度一下,说不定刚刚释放的这个线程就是优先级最高的那个线程。
307RAW_U16 raw_task_delete(RAW_TASK_OBJ *task_ptr)
308 {
309 RAW_SR_ALLOC();
310
311 #if (RAW_TASK_FUNCTION_CHECK > 0)
312
313if (task_ptr == 0) {
314
315return RAW_NULL_OBJECT;
316 }
317
318if (raw_int_nesting) {
319
320return RAW_NOT_CALLED_BY_ISR;
321
322 }
323
324 #endif
325
326if (task_ptr->priority == IDLE_PRIORITY) {
327
328return RAW_DELETE_TASK_NOT_ALLOWED;
329 }
330
331 RAW_CRITICAL_ENTER();
332
333if (task_ptr == raw_task_active) {
334
335if (raw_sched_lock) {
336 RAW_CRITICAL_EXIT();
337return RAW_SCHED_LOCKED;
338 }
339 }
340
341switch (task_ptr->task_state) {
软件英才网软件行业驰名招聘网站
342case RAW_RDY:
343 remove_ready_list(&raw_ready_queue, task_ptr);
344break;
345
346case RAW_SUSPENDED:
347break;
348
349case RAW_DLY: /* Task is only delayed, not on any wait list */
350case RAW_DLY_SUSPENDED:
351 tick_list_remove(task_ptr);
352break;
353
354case RAW_PEND:
355case RAW_PEND_SUSPENDED:
356case RAW_PEND_TIMEOUT:
357case RAW_PEND_TIMEOUT_SUSPENDED:
358 tick_list_remove(task_ptr);
359 list_delete(&task_ptr->task_list);
360break;
361
362default:
363
364 #if (CONFIG_RAW_ASSERT > 0)
365 RAW_ASSERT(0);
366 #endif
367
368 RAW_CRITICAL_EXIT();
369return RAW_STATE_UNKNOWN;
370 }
371
372 task_ptr->task_state = RAW_DELETED;
373
374 #if (RAW_TASK_STACK_CHECK > 0)
375/*make after_delete_list to right position*/
376 after_delete_list = task_ptr->stack_check_list.next;
377
378if (after_delete_list == &task_head) {
379 after_delete_list = task_head.next;
380 }
381
382 list_delete(&task_ptr->stack_check_list);
软件英才网 软件行业驰名招聘网站
有需要请联系我们 384 #endif
385
386 RAW_CRITICAL_EXIT();
387
388 raw_sched();
389
390 return RAW_SUCCESS;
391 }
392
删除函数的动作其实是比较残忍的,因为此时你不清楚线程已经执行到哪一步了,拥有了那些资源,正在处理哪些资源,所以没事不要用这个函数。
这里做的只是把任务从就绪队列、等待队列和阻塞队列清除出来,但是真正善后的工作要比这多得多,如果有兴趣,你看看linux 的exit 函数就明白了。