1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2006-03-28 Bernard first version
9 * 2006-04-29 Bernard implement thread timer
10 * 2006-04-30 Bernard added THREAD_DEBUG
11 * 2006-05-27 Bernard fixed the rt_thread_yield bug
12 * 2006-06-03 Bernard fixed the thread timer init bug
13 * 2006-08-10 Bernard fixed the timer bug in thread_sleep
14 * 2006-09-03 Bernard changed rt_timer_delete to rt_timer_detach
15 * 2006-09-03 Bernard implement rt_thread_detach
16 * 2008-02-16 Bernard fixed the rt_thread_timeout bug
17 * 2010-03-21 Bernard change the errno of rt_thread_delay/sleep to
18 * RT_EOK.
19 * 2010-11-10 Bernard add cleanup callback function in thread exit.
20 * 2011-09-01 Bernard fixed rt_thread_exit issue when the current
21 * thread preempted, which reported by Jiaxing Lee.
22 * 2011-09-08 Bernard fixed the scheduling issue in rt_thread_startup.
23 * 2012-12-29 Bernard fixed compiling warning.
24 * 2016-08-09 ArdaFu add thread suspend and resume hook.
25 * 2017-04-10 armink fixed the rt_thread_delete and rt_thread_detach
26 * bug when thread has not startup.
27 * 2018-11-22 Jesven yield is same to rt_schedule
28 * add support for tasks bound to cpu
29 */
30
31 #include <rthw.h>
32 #include <rtthread.h>
33
34 extern rt_list_t rt_thread_defunct;
35
36 #ifdef RT_USING_HOOK
37 static void (*rt_thread_suspend_hook)(rt_thread_t thread);
38 static void (*rt_thread_resume_hook) (rt_thread_t thread);
39 static void (*rt_thread_inited_hook) (rt_thread_t thread);
40
41 /**
42 * @ingroup Hook
43 * This function sets a hook function when the system suspend a thread.
44 *
45 * @param hook the specified hook function
46 *
47 * @note the hook function must be simple and never be blocked or suspend.
48 */
rt_thread_suspend_sethook(void (* hook)(rt_thread_t thread))49 void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread))
50 {
51 rt_thread_suspend_hook = hook;
52 }
53
54 /**
55 * @ingroup Hook
56 * This function sets a hook function when the system resume a thread.
57 *
58 * @param hook the specified hook function
59 *
60 * @note the hook function must be simple and never be blocked or suspend.
61 */
rt_thread_resume_sethook(void (* hook)(rt_thread_t thread))62 void rt_thread_resume_sethook(void (*hook)(rt_thread_t thread))
63 {
64 rt_thread_resume_hook = hook;
65 }
66
67 /**
68 * @ingroup Hook
69 * This function sets a hook function when a thread is initialized.
70 *
71 * @param hook the specified hook function
72 */
rt_thread_inited_sethook(void (* hook)(rt_thread_t thread))73 void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread))
74 {
75 rt_thread_inited_hook = hook;
76 }
77
78 #endif
79
rt_thread_exit(void)80 void rt_thread_exit(void)
81 {
82 struct rt_thread *thread;
83 register rt_base_t level;
84
85 /* get current thread */
86 thread = rt_thread_self();
87
88 /* disable interrupt */
89 level = rt_hw_interrupt_disable();
90
91 /* remove from schedule */
92 rt_schedule_remove_thread(thread);
93 /* change stat */
94 thread->stat = RT_THREAD_CLOSE;
95
96 /* remove it from timer list */
97 rt_timer_detach(&thread->thread_timer);
98
99 if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
100 thread->cleanup == RT_NULL)
101 {
102 rt_object_detach((rt_object_t)thread);
103 }
104 else
105 {
106 /* insert to defunct thread list */
107 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
108 }
109
110 /* enable interrupt */
111 rt_hw_interrupt_enable(level);
112
113 /* switch to next task */
114 rt_schedule();
115 }
116
_rt_thread_init(struct rt_thread * thread,const char * name,void (* entry)(void * parameter),void * parameter,void * stack_start,rt_uint32_t stack_size,rt_uint8_t priority,rt_uint32_t tick)117 static rt_err_t _rt_thread_init(struct rt_thread *thread,
118 const char *name,
119 void (*entry)(void *parameter),
120 void *parameter,
121 void *stack_start,
122 rt_uint32_t stack_size,
123 rt_uint8_t priority,
124 rt_uint32_t tick)
125 {
126 /* init thread list */
127 rt_list_init(&(thread->tlist));
128
129 thread->entry = (void *)entry;
130 thread->parameter = parameter;
131
132 /* stack init */
133 thread->stack_addr = stack_start;
134 thread->stack_size = stack_size;
135
136 /* init thread stack */
137 rt_memset(thread->stack_addr, '#', thread->stack_size);
138 #ifdef ARCH_CPU_STACK_GROWS_UPWARD
139 thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
140 (void *)((char *)thread->stack_addr),
141 (void *)rt_thread_exit);
142 #else
143 thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
144 (void *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
145 (void *)rt_thread_exit);
146 #endif
147
148 /* priority init */
149 RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
150 thread->init_priority = priority;
151 thread->current_priority = priority;
152
153 thread->number_mask = 0;
154 #if RT_THREAD_PRIORITY_MAX > 32
155 thread->number = 0;
156 thread->high_mask = 0;
157 #endif
158
159 /* tick init */
160 thread->init_tick = tick;
161 thread->remaining_tick = tick;
162
163 /* error and flags */
164 thread->error = RT_EOK;
165 thread->stat = RT_THREAD_INIT;
166
167 #ifdef RT_USING_SMP
168 /* not bind on any cpu */
169 thread->bind_cpu = RT_CPUS_NR;
170 thread->oncpu = RT_CPU_DETACHED;
171
172 /* lock init */
173 thread->scheduler_lock_nest = 0;
174 thread->cpus_lock_nest = 0;
175 #endif /*RT_USING_SMP*/
176
177 /* initialize cleanup function and user data */
178 thread->cleanup = 0;
179 thread->user_data = 0;
180
181 /* init thread timer */
182 rt_timer_init(&(thread->thread_timer),
183 thread->name,
184 rt_thread_timeout,
185 thread,
186 0,
187 RT_TIMER_FLAG_ONE_SHOT);
188
189 /* initialize signal */
190 #ifdef RT_USING_SIGNALS
191 thread->sig_mask = 0x00;
192 thread->sig_pending = 0x00;
193
194 thread->sig_ret = RT_NULL;
195 thread->sig_vectors = RT_NULL;
196 thread->si_list = RT_NULL;
197 #endif
198
199 #ifdef RT_USING_LWP
200 thread->lwp = RT_NULL;
201 #endif
202
203 RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
204
205 return RT_EOK;
206 }
207
208 /**
209 * @addtogroup Thread
210 */
211
212 /**@{*/
213
214 /**
215 * This function will initialize a thread, normally it's used to initialize a
216 * static thread object.
217 *
218 * @param thread the static thread object
219 * @param name the name of thread, which shall be unique
220 * @param entry the entry function of thread
221 * @param parameter the parameter of thread enter function
222 * @param stack_start the start address of thread stack
223 * @param stack_size the size of thread stack
224 * @param priority the priority of thread
225 * @param tick the time slice if there are same priority thread
226 *
227 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
228 */
rt_thread_init(struct rt_thread * thread,const char * name,void (* entry)(void * parameter),void * parameter,void * stack_start,rt_uint32_t stack_size,rt_uint8_t priority,rt_uint32_t tick)229 rt_err_t rt_thread_init(struct rt_thread *thread,
230 const char *name,
231 void (*entry)(void *parameter),
232 void *parameter,
233 void *stack_start,
234 rt_uint32_t stack_size,
235 rt_uint8_t priority,
236 rt_uint32_t tick)
237 {
238 /* thread check */
239 RT_ASSERT(thread != RT_NULL);
240 RT_ASSERT(stack_start != RT_NULL);
241
242 /* init thread object */
243 rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
244
245 return _rt_thread_init(thread,
246 name,
247 entry,
248 parameter,
249 stack_start,
250 stack_size,
251 priority,
252 tick);
253 }
254 RTM_EXPORT(rt_thread_init);
255
256 /**
257 * This function will return self thread object
258 *
259 * @return the self thread object
260 */
rt_thread_self(void)261 rt_thread_t rt_thread_self(void)
262 {
263 #ifdef RT_USING_SMP
264 rt_base_t lock;
265 rt_thread_t self;
266
267 lock = rt_hw_local_irq_disable();
268 self = rt_cpu_self()->current_thread;
269 rt_hw_local_irq_enable(lock);
270 return self;
271 #else
272 extern rt_thread_t rt_current_thread;
273
274 return rt_current_thread;
275 #endif
276 }
277 RTM_EXPORT(rt_thread_self);
278
279 /**
280 * This function will start a thread and put it to system ready queue
281 *
282 * @param thread the thread to be started
283 *
284 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
285 */
rt_thread_startup(rt_thread_t thread)286 rt_err_t rt_thread_startup(rt_thread_t thread)
287 {
288 /* thread check */
289 RT_ASSERT(thread != RT_NULL);
290 RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT);
291 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
292
293 /* set current priority to init priority */
294 thread->current_priority = thread->init_priority;
295
296 /* calculate priority attribute */
297 #if RT_THREAD_PRIORITY_MAX > 32
298 thread->number = thread->current_priority >> 3; /* 5bit */
299 thread->number_mask = 1L << thread->number;
300 thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */
301 #else
302 thread->number_mask = 1L << thread->current_priority;
303 #endif
304
305 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n",
306 thread->name, thread->init_priority));
307 /* change thread stat */
308 thread->stat = RT_THREAD_SUSPEND;
309 /* then resume it */
310 rt_thread_resume(thread);
311 if (rt_thread_self() != RT_NULL)
312 {
313 /* do a scheduling */
314 rt_schedule();
315 }
316
317 return RT_EOK;
318 }
319 RTM_EXPORT(rt_thread_startup);
320
321 /**
322 * This function will detach a thread. The thread object will be removed from
323 * thread queue and detached/deleted from system object management.
324 *
325 * @param thread the thread to be deleted
326 *
327 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
328 */
rt_thread_detach(rt_thread_t thread)329 rt_err_t rt_thread_detach(rt_thread_t thread)
330 {
331 rt_base_t lock;
332
333 /* thread check */
334 RT_ASSERT(thread != RT_NULL);
335 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
336 RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread));
337
338 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
339 {
340 /* remove from schedule */
341 rt_schedule_remove_thread(thread);
342 }
343
344 /* release thread timer */
345 rt_timer_detach(&(thread->thread_timer));
346
347 /* change stat */
348 thread->stat = RT_THREAD_CLOSE;
349
350 /* detach object */
351 rt_object_detach((rt_object_t)thread);
352
353 if (thread->cleanup != RT_NULL)
354 {
355 /* disable interrupt */
356 lock = rt_hw_interrupt_disable();
357
358 /* insert to defunct thread list */
359 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
360
361 /* enable interrupt */
362 rt_hw_interrupt_enable(lock);
363 }
364
365 return RT_EOK;
366 }
367 RTM_EXPORT(rt_thread_detach);
368
369
370 #ifdef RT_USING_HEAP
371 /**
372 * This function will create a thread object and allocate thread object memory
373 * and stack.
374 *
375 * @param name the name of thread, which shall be unique
376 * @param entry the entry function of thread
377 * @param parameter the parameter of thread enter function
378 * @param stack_size the size of thread stack
379 * @param priority the priority of thread
380 * @param tick the time slice if there are same priority thread
381 *
382 * @return the created thread object
383 */
rt_thread_create(const char * name,void (* entry)(void * parameter),void * parameter,rt_uint32_t stack_size,rt_uint8_t priority,rt_uint32_t tick)384 rt_thread_t rt_thread_create(const char *name,
385 void (*entry)(void *parameter),
386 void *parameter,
387 rt_uint32_t stack_size,
388 rt_uint8_t priority,
389 rt_uint32_t tick)
390 {
391 struct rt_thread *thread;
392 void *stack_start;
393
394 thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
395 name);
396 if (thread == RT_NULL)
397 return RT_NULL;
398
399 stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
400 if (stack_start == RT_NULL)
401 {
402 /* allocate stack failure */
403 rt_object_delete((rt_object_t)thread);
404
405 return RT_NULL;
406 }
407
408 _rt_thread_init(thread,
409 name,
410 entry,
411 parameter,
412 stack_start,
413 stack_size,
414 priority,
415 tick);
416
417 return thread;
418 }
419 RTM_EXPORT(rt_thread_create);
420
421 /**
422 * This function will delete a thread. The thread object will be removed from
423 * thread queue and deleted from system object management in the idle thread.
424 *
425 * @param thread the thread to be deleted
426 *
427 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
428 */
rt_thread_delete(rt_thread_t thread)429 rt_err_t rt_thread_delete(rt_thread_t thread)
430 {
431 rt_base_t lock;
432
433 /* thread check */
434 RT_ASSERT(thread != RT_NULL);
435 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
436 RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE);
437
438 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
439 {
440 /* remove from schedule */
441 rt_schedule_remove_thread(thread);
442 }
443
444 /* release thread timer */
445 rt_timer_detach(&(thread->thread_timer));
446
447 /* change stat */
448 thread->stat = RT_THREAD_CLOSE;
449
450 /* disable interrupt */
451 lock = rt_hw_interrupt_disable();
452
453 /* insert to defunct thread list */
454 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
455
456 /* enable interrupt */
457 rt_hw_interrupt_enable(lock);
458
459 return RT_EOK;
460 }
461 RTM_EXPORT(rt_thread_delete);
462 #endif
463
464 /**
465 * This function will let current thread yield processor, and scheduler will
466 * choose a highest thread to run. After yield processor, the current thread
467 * is still in READY state.
468 *
469 * @return RT_EOK
470 */
rt_thread_yield(void)471 rt_err_t rt_thread_yield(void)
472 {
473 rt_schedule();
474
475 return RT_EOK;
476 }
477 RTM_EXPORT(rt_thread_yield);
478
479 /**
480 * This function will let current thread sleep for some ticks.
481 *
482 * @param tick the sleep ticks
483 *
484 * @return RT_EOK
485 */
rt_thread_sleep(rt_tick_t tick)486 rt_err_t rt_thread_sleep(rt_tick_t tick)
487 {
488 register rt_base_t temp;
489 struct rt_thread *thread;
490
491 /* set to current thread */
492 thread = rt_thread_self();
493 RT_ASSERT(thread != RT_NULL);
494 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
495
496 /* disable interrupt */
497 temp = rt_hw_interrupt_disable();
498
499 /* suspend thread */
500 rt_thread_suspend(thread);
501
502 /* reset the timeout of thread timer and start it */
503 rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
504 rt_timer_start(&(thread->thread_timer));
505
506 /* enable interrupt */
507 rt_hw_interrupt_enable(temp);
508
509 rt_schedule();
510
511 /* clear error number of this thread to RT_EOK */
512 if (thread->error == -RT_ETIMEOUT)
513 thread->error = RT_EOK;
514
515 return RT_EOK;
516 }
517
518 /**
519 * This function will let current thread delay for some ticks.
520 *
521 * @param tick the delay ticks
522 *
523 * @return RT_EOK
524 */
rt_thread_delay(rt_tick_t tick)525 rt_err_t rt_thread_delay(rt_tick_t tick)
526 {
527 return rt_thread_sleep(tick);
528 }
529 RTM_EXPORT(rt_thread_delay);
530
531 /**
532 * This function will let current thread delay for some milliseconds.
533 *
534 * @param tick the delay time
535 *
536 * @return RT_EOK
537 */
rt_thread_mdelay(rt_int32_t ms)538 rt_err_t rt_thread_mdelay(rt_int32_t ms)
539 {
540 rt_tick_t tick;
541
542 tick = rt_tick_from_millisecond(ms);
543
544 return rt_thread_sleep(tick);
545 }
546 RTM_EXPORT(rt_thread_mdelay);
547
548 /**
549 * This function will control thread behaviors according to control command.
550 *
551 * @param thread the specified thread to be controlled
552 * @param cmd the control command, which includes
553 * RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread;
554 * RT_THREAD_CTRL_STARTUP for starting a thread;
555 * RT_THREAD_CTRL_CLOSE for delete a thread;
556 * RT_THREAD_CTRL_BIND_CPU for bind the thread to a CPU.
557 * @param arg the argument of control command
558 *
559 * @return RT_EOK
560 */
rt_thread_control(rt_thread_t thread,int cmd,void * arg)561 rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
562 {
563 register rt_base_t temp;
564
565 /* thread check */
566 RT_ASSERT(thread != RT_NULL);
567 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
568
569 switch (cmd)
570 {
571 case RT_THREAD_CTRL_CHANGE_PRIORITY:
572 /* disable interrupt */
573 temp = rt_hw_interrupt_disable();
574
575 /* for ready thread, change queue */
576 if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
577 {
578 /* remove thread from schedule queue first */
579 rt_schedule_remove_thread(thread);
580
581 /* change thread priority */
582 thread->current_priority = *(rt_uint8_t *)arg;
583
584 /* recalculate priority attribute */
585 #if RT_THREAD_PRIORITY_MAX > 32
586 thread->number = thread->current_priority >> 3; /* 5bit */
587 thread->number_mask = 1 << thread->number;
588 thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
589 #else
590 thread->number_mask = 1 << thread->current_priority;
591 #endif
592
593 /* insert thread to schedule queue again */
594 rt_schedule_insert_thread(thread);
595 }
596 else
597 {
598 thread->current_priority = *(rt_uint8_t *)arg;
599
600 /* recalculate priority attribute */
601 #if RT_THREAD_PRIORITY_MAX > 32
602 thread->number = thread->current_priority >> 3; /* 5bit */
603 thread->number_mask = 1 << thread->number;
604 thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
605 #else
606 thread->number_mask = 1 << thread->current_priority;
607 #endif
608 }
609
610 /* enable interrupt */
611 rt_hw_interrupt_enable(temp);
612 break;
613
614 case RT_THREAD_CTRL_STARTUP:
615 return rt_thread_startup(thread);
616
617 #ifdef RT_USING_HEAP
618 case RT_THREAD_CTRL_CLOSE:
619 return rt_thread_delete(thread);
620 #endif
621
622 #ifdef RT_USING_SMP
623 case RT_THREAD_CTRL_BIND_CPU:
624 {
625 rt_uint8_t cpu;
626
627 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
628 {
629 /* we only support bind cpu before started phase. */
630 return RT_ERROR;
631 }
632
633 cpu = (rt_uint8_t)(size_t)arg;
634 thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu;
635 break;
636 }
637 #endif /*RT_USING_SMP*/
638 default:
639 break;
640 }
641
642 return RT_EOK;
643 }
644 RTM_EXPORT(rt_thread_control);
645
646 /**
647 * This function will suspend the specified thread.
648 *
649 * @param thread the thread to be suspended
650 *
651 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
652 *
653 * @note if suspend self thread, after this function call, the
654 * rt_schedule() must be invoked.
655 */
rt_thread_suspend(rt_thread_t thread)656 rt_err_t rt_thread_suspend(rt_thread_t thread)
657 {
658 register rt_base_t stat;
659 register rt_base_t temp;
660
661 /* thread check */
662 RT_ASSERT(thread != RT_NULL);
663 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
664
665 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name));
666
667 stat = thread->stat & RT_THREAD_STAT_MASK;
668 if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING))
669 {
670 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n",
671 thread->stat));
672 return -RT_ERROR;
673 }
674
675 /* disable interrupt */
676 temp = rt_hw_interrupt_disable();
677 if (stat == RT_THREAD_RUNNING)
678 {
679 /* not suspend running status thread on other core */
680 RT_ASSERT(thread == rt_thread_self());
681 }
682
683 /* change thread stat */
684 rt_schedule_remove_thread(thread);
685 thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
686
687 /* stop thread timer anyway */
688 rt_timer_stop(&(thread->thread_timer));
689
690 /* enable interrupt */
691 rt_hw_interrupt_enable(temp);
692
693 RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread));
694 return RT_EOK;
695 }
696 RTM_EXPORT(rt_thread_suspend);
697
698 /**
699 * This function will resume a thread and put it to system ready queue.
700 *
701 * @param thread the thread to be resumed
702 *
703 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
704 */
rt_thread_resume(rt_thread_t thread)705 rt_err_t rt_thread_resume(rt_thread_t thread)
706 {
707 register rt_base_t temp;
708
709 /* thread check */
710 RT_ASSERT(thread != RT_NULL);
711 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
712
713 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name));
714
715 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
716 {
717 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
718 thread->stat));
719
720 return -RT_ERROR;
721 }
722
723 /* disable interrupt */
724 temp = rt_hw_interrupt_disable();
725
726 /* remove from suspend list */
727 rt_list_remove(&(thread->tlist));
728
729 rt_timer_stop(&thread->thread_timer);
730
731 /* enable interrupt */
732 rt_hw_interrupt_enable(temp);
733
734 /* insert to schedule ready list */
735 rt_schedule_insert_thread(thread);
736
737 RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread));
738 return RT_EOK;
739 }
740 RTM_EXPORT(rt_thread_resume);
741
742 /**
743 * This function is the timeout function for thread, normally which is invoked
744 * when thread is timeout to wait some resource.
745 *
746 * @param parameter the parameter of thread timeout function
747 */
rt_thread_timeout(void * parameter)748 void rt_thread_timeout(void *parameter)
749 {
750 struct rt_thread *thread;
751
752 thread = (struct rt_thread *)parameter;
753
754 /* thread check */
755 RT_ASSERT(thread != RT_NULL);
756 RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
757 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
758
759 /* set error number */
760 thread->error = -RT_ETIMEOUT;
761
762 /* remove from suspend list */
763 rt_list_remove(&(thread->tlist));
764
765 /* insert to schedule ready list */
766 rt_schedule_insert_thread(thread);
767
768 /* do schedule */
769 rt_schedule();
770 }
771 RTM_EXPORT(rt_thread_timeout);
772
773 /**
774 * This function will find the specified thread.
775 *
776 * @param name the name of thread finding
777 *
778 * @return the found thread
779 *
780 * @note please don't invoke this function in interrupt status.
781 */
rt_thread_find(char * name)782 rt_thread_t rt_thread_find(char *name)
783 {
784 struct rt_object_information *information;
785 struct rt_object *object;
786 struct rt_list_node *node;
787
788 /* enter critical */
789 if (rt_thread_self() != RT_NULL)
790 rt_enter_critical();
791
792 /* try to find device object */
793 information = rt_object_get_information(RT_Object_Class_Thread);
794 RT_ASSERT(information != RT_NULL);
795 for (node = information->object_list.next;
796 node != &(information->object_list);
797 node = node->next)
798 {
799 object = rt_list_entry(node, struct rt_object, list);
800 if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
801 {
802 /* leave critical */
803 if (rt_thread_self() != RT_NULL)
804 rt_exit_critical();
805
806 return (rt_thread_t)object;
807 }
808 }
809
810 /* leave critical */
811 if (rt_thread_self() != RT_NULL)
812 rt_exit_critical();
813
814 /* not found */
815 return RT_NULL;
816 }
817 RTM_EXPORT(rt_thread_find);
818
819 /**@}*/
820