defunct.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-08-30 heyuanjie87 the first version
  9. *
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #ifndef SYSTEM_THREAD_STACK_SIZE
  14. #define SYSTEM_THREAD_STACK_SIZE IDLE_THREAD_STACK_SIZE
  15. #endif
  16. static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct);
  17. static struct rt_spinlock _defunct_spinlock;
  18. #if defined(RT_USING_SMP) || defined(RT_USING_SMART)
  19. static struct rt_thread rt_system_thread;
  20. rt_align(RT_ALIGN_SIZE) static rt_uint8_t rt_system_stack[SYSTEM_THREAD_STACK_SIZE];
  21. static struct rt_semaphore system_sem;
  22. #endif
  23. /**
  24. * @brief Enqueue a thread to defunct queue.
  25. *
  26. * @param thread the thread to be enqueued.
  27. *
  28. * @note It must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable
  29. */
  30. void rt_thread_defunct_enqueue(rt_thread_t thread)
  31. {
  32. rt_base_t level;
  33. level = rt_spin_lock_irqsave(&_defunct_spinlock);
  34. rt_list_insert_after(&_rt_thread_defunct, &RT_THREAD_LIST_NODE(thread));
  35. rt_spin_unlock_irqrestore(&_defunct_spinlock, level);
  36. #if defined(RT_USING_SMP) || defined(RT_USING_SMART)
  37. rt_sem_release(&system_sem);
  38. #endif
  39. }
  40. /**
  41. * @brief Dequeue a thread from defunct queue.
  42. */
  43. rt_thread_t rt_thread_defunct_dequeue(void)
  44. {
  45. rt_base_t level;
  46. rt_thread_t thread = RT_NULL;
  47. rt_list_t *l = &_rt_thread_defunct;
  48. level = rt_spin_lock_irqsave(&_defunct_spinlock);
  49. if (!rt_list_isempty(l))
  50. {
  51. thread = RT_THREAD_LIST_NODE_ENTRY(l->next);
  52. rt_list_remove(&RT_THREAD_LIST_NODE(thread));
  53. }
  54. rt_spin_unlock_irqrestore(&_defunct_spinlock, level);
  55. return thread;
  56. }
  57. /**
  58. * @brief This function will perform system background job when system idle.
  59. */
  60. void rt_defunct_execute(void)
  61. {
  62. /* Loop until there is no dead thread. So one call to rt_defunct_execute
  63. * will do all the cleanups. */
  64. while (1)
  65. {
  66. rt_thread_t thread;
  67. rt_bool_t object_is_systemobject;
  68. void (*cleanup)(struct rt_thread *tid);
  69. #ifdef RT_USING_MODULE
  70. struct rt_dlmodule *module = RT_NULL;
  71. #endif
  72. /* get defunct thread */
  73. thread = rt_thread_defunct_dequeue();
  74. if (thread == RT_NULL)
  75. {
  76. break;
  77. }
  78. #ifdef RT_USING_MODULE
  79. module = (struct rt_dlmodule *)thread->parent.module_id;
  80. if (module)
  81. {
  82. dlmodule_destroy(module);
  83. }
  84. #endif
  85. #ifdef RT_USING_SIGNALS
  86. rt_thread_free_sig(thread);
  87. #endif
  88. /* store the point of "thread->cleanup" avoid to lose */
  89. cleanup = thread->cleanup;
  90. /* if it's a system object, detach it */
  91. object_is_systemobject = rt_object_is_systemobject((rt_object_t)thread);
  92. if (object_is_systemobject == RT_TRUE)
  93. {
  94. /* detach this object */
  95. rt_object_detach((rt_object_t)thread);
  96. }
  97. /* invoke thread cleanup */
  98. if (cleanup != RT_NULL)
  99. {
  100. cleanup(thread);
  101. }
  102. #ifdef RT_USING_HEAP
  103. #ifdef RT_USING_MEM_PROTECTION
  104. if (thread->mem_regions != RT_NULL)
  105. {
  106. RT_KERNEL_FREE(thread->mem_regions);
  107. }
  108. #endif
  109. /* if need free, delete it */
  110. if (object_is_systemobject == RT_FALSE)
  111. {
  112. /* release thread's stack */
  113. #ifdef RT_USING_HW_STACK_GUARD
  114. RT_KERNEL_FREE(thread->stack_buf);
  115. #else
  116. RT_KERNEL_FREE(thread->stack_addr);
  117. #endif
  118. /* delete thread object */
  119. rt_object_delete((rt_object_t)thread);
  120. }
  121. #endif
  122. }
  123. }
  124. #if defined(RT_USING_SMP) || defined(RT_USING_SMART)
  125. static void rt_thread_system_entry(void *parameter)
  126. {
  127. RT_UNUSED(parameter);
  128. while (1)
  129. {
  130. int ret = rt_sem_take(&system_sem, RT_WAITING_FOREVER);
  131. if (ret != RT_EOK)
  132. {
  133. rt_kprintf("failed to sem_take() error %d\n", ret);
  134. RT_ASSERT(0);
  135. }
  136. rt_defunct_execute();
  137. }
  138. }
  139. #endif
  140. void rt_thread_defunct_init(void)
  141. {
  142. RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2);
  143. rt_spin_lock_init(&_defunct_spinlock);
  144. #if defined(RT_USING_SMP) || defined(RT_USING_SMART)
  145. rt_sem_init(&system_sem, "defunct", 0, RT_IPC_FLAG_FIFO);
  146. /* create defunct thread */
  147. rt_thread_init(&rt_system_thread,
  148. "tsystem",
  149. rt_thread_system_entry,
  150. RT_NULL,
  151. rt_system_stack,
  152. sizeof(rt_system_stack),
  153. RT_THREAD_PRIORITY_MAX - 2,
  154. 32);
  155. /* startup */
  156. rt_thread_startup(&rt_system_thread);
  157. #endif
  158. }