thread.c 29 KB

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