1
0

lwp_tid.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. * 2021-01-15 shaojinchun first version
  9. * 2023-11-16 xqyjlj Fix the case where tid is 0
  10. */
  11. #define DBG_TAG "lwp.tid"
  12. #define DBG_LVL DBG_LOG
  13. #include <rtdbg.h>
  14. #include <rthw.h>
  15. #include <rtthread.h>
  16. #include "lwp_internal.h"
  17. #ifdef ARCH_MM_MMU
  18. #include "lwp_user_mm.h"
  19. #endif
  20. #define TID_MAX 10000
  21. #define TID_CT_ASSERT(name, x) \
  22. struct assert_##name {char ary[2 * (x) - 1];}
  23. TID_CT_ASSERT(tid_min_nr, LWP_TID_MAX_NR > 1);
  24. TID_CT_ASSERT(tid_max_nr, LWP_TID_MAX_NR < TID_MAX);
  25. static struct lwp_avl_struct lwp_tid_ary[LWP_TID_MAX_NR];
  26. static struct lwp_avl_struct *lwp_tid_free_head = RT_NULL;
  27. static int lwp_tid_ary_alloced = 0;
  28. static struct lwp_avl_struct *lwp_tid_root = RT_NULL;
  29. static int current_tid = 0;
  30. static struct rt_mutex tid_lock;
  31. int lwp_tid_init(void)
  32. {
  33. return rt_mutex_init(&tid_lock, "tidmtx", RT_IPC_FLAG_PRIO);
  34. }
  35. int lwp_tid_get(void)
  36. {
  37. struct lwp_avl_struct *p;
  38. int tid = 0;
  39. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  40. p = lwp_tid_free_head;
  41. if (p)
  42. {
  43. lwp_tid_free_head = (struct lwp_avl_struct *)p->avl_right;
  44. }
  45. else if (lwp_tid_ary_alloced < LWP_TID_MAX_NR)
  46. {
  47. p = lwp_tid_ary + lwp_tid_ary_alloced;
  48. lwp_tid_ary_alloced++;
  49. }
  50. if (p)
  51. {
  52. int found_noused = 0;
  53. RT_ASSERT(p->data == RT_NULL);
  54. for (tid = current_tid + 1; tid < TID_MAX; tid++)
  55. {
  56. if (!lwp_avl_find(tid, lwp_tid_root))
  57. {
  58. found_noused = 1;
  59. break;
  60. }
  61. }
  62. if (!found_noused)
  63. {
  64. for (tid = 1; tid <= current_tid; tid++)
  65. {
  66. if (!lwp_avl_find(tid, lwp_tid_root))
  67. {
  68. found_noused = 1;
  69. break;
  70. }
  71. }
  72. }
  73. p->avl_key = tid;
  74. lwp_avl_insert(p, &lwp_tid_root);
  75. current_tid = tid;
  76. }
  77. lwp_mutex_release_safe(&tid_lock);
  78. if (tid <= 0)
  79. {
  80. LOG_W("resource TID exhausted.");
  81. }
  82. return tid;
  83. }
  84. void lwp_tid_put(int tid)
  85. {
  86. struct lwp_avl_struct *p;
  87. rt_thread_t thread;
  88. rt_thread_t current;
  89. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  90. p = lwp_avl_find(tid, lwp_tid_root);
  91. if (p)
  92. {
  93. thread = p->data;
  94. p->data = RT_NULL;
  95. lwp_avl_remove(p, &lwp_tid_root);
  96. p->avl_right = lwp_tid_free_head;
  97. lwp_tid_free_head = p;
  98. }
  99. else
  100. thread = RT_NULL;
  101. if (thread && thread->tid_ref_count)
  102. {
  103. current = rt_thread_self();
  104. RT_ASSERT(thread->susp_recycler == RT_NULL);
  105. thread->susp_recycler = current;
  106. rt_enter_critical();
  107. rt_thread_suspend_with_flag(current, RT_UNINTERRUPTIBLE);
  108. lwp_mutex_release_safe(&tid_lock);
  109. rt_exit_critical();
  110. rt_schedule();
  111. }
  112. else
  113. lwp_mutex_release_safe(&tid_lock);
  114. }
  115. rt_thread_t lwp_tid_get_thread_raw(int tid)
  116. {
  117. struct lwp_avl_struct *p;
  118. rt_thread_t thread = RT_NULL;
  119. p = lwp_avl_find(tid, lwp_tid_root);
  120. if (p)
  121. {
  122. thread = (rt_thread_t)p->data;
  123. }
  124. return thread;
  125. }
  126. rt_thread_t lwp_tid_get_thread_and_inc_ref(int tid)
  127. {
  128. rt_thread_t thread = RT_NULL;
  129. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  130. thread = tid ? lwp_tid_get_thread_raw(tid) : rt_thread_self();
  131. if (thread != RT_NULL)
  132. {
  133. thread->tid_ref_count += 1;
  134. }
  135. lwp_mutex_release_safe(&tid_lock);
  136. return thread;
  137. }
  138. void lwp_tid_dec_ref(rt_thread_t thread)
  139. {
  140. rt_thread_t susp_putter;
  141. if (thread)
  142. {
  143. RT_ASSERT(rt_object_get_type(&thread->parent) == RT_Object_Class_Thread);
  144. susp_putter = thread->susp_recycler;
  145. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  146. RT_ASSERT(thread->tid_ref_count > 0);
  147. thread->tid_ref_count -= 1;
  148. if (!thread->tid_ref_count && susp_putter)
  149. {
  150. rt_thread_resume(susp_putter);
  151. }
  152. lwp_mutex_release_safe(&tid_lock);
  153. }
  154. }
  155. void lwp_tid_set_thread(int tid, rt_thread_t thread)
  156. {
  157. struct lwp_avl_struct *p;
  158. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  159. p = lwp_avl_find(tid, lwp_tid_root);
  160. if (p)
  161. {
  162. RT_ASSERT(p->data == RT_NULL);
  163. p->data = thread;
  164. }
  165. lwp_mutex_release_safe(&tid_lock);
  166. }