xref: /nrf52832-nimble/rt-thread/src/thread.c (revision 104654410c56c573564690304ae786df310c91fc)
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