lwp_tid.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. return tid;
  79. }
  80. void lwp_tid_put(int tid)
  81. {
  82. struct lwp_avl_struct *p;
  83. rt_thread_t thread;
  84. rt_thread_t current;
  85. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  86. p = lwp_avl_find(tid, lwp_tid_root);
  87. if (p)
  88. {
  89. thread = p->data;
  90. p->data = RT_NULL;
  91. lwp_avl_remove(p, &lwp_tid_root);
  92. p->avl_right = lwp_tid_free_head;
  93. lwp_tid_free_head = p;
  94. }
  95. else
  96. thread = RT_NULL;
  97. if (thread && thread->tid_ref_count)
  98. {
  99. current = rt_thread_self();
  100. RT_ASSERT(thread->susp_recycler == RT_NULL);
  101. thread->susp_recycler = current;
  102. rt_enter_critical();
  103. rt_thread_suspend_with_flag(current, RT_UNINTERRUPTIBLE);
  104. lwp_mutex_release_safe(&tid_lock);
  105. rt_exit_critical();
  106. rt_schedule();
  107. }
  108. else
  109. lwp_mutex_release_safe(&tid_lock);
  110. }
  111. rt_thread_t lwp_tid_get_thread_raw(int tid)
  112. {
  113. struct lwp_avl_struct *p;
  114. rt_thread_t thread = RT_NULL;
  115. p = lwp_avl_find(tid, lwp_tid_root);
  116. if (p)
  117. {
  118. thread = (rt_thread_t)p->data;
  119. }
  120. return thread;
  121. }
  122. rt_thread_t lwp_tid_get_thread_and_inc_ref(int tid)
  123. {
  124. rt_thread_t thread = RT_NULL;
  125. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  126. thread = tid ? lwp_tid_get_thread_raw(tid) : rt_thread_self();
  127. if (thread != RT_NULL)
  128. {
  129. thread->tid_ref_count += 1;
  130. }
  131. lwp_mutex_release_safe(&tid_lock);
  132. return thread;
  133. }
  134. void lwp_tid_dec_ref(rt_thread_t thread)
  135. {
  136. rt_thread_t susp_putter;
  137. if (thread)
  138. {
  139. RT_ASSERT(rt_object_get_type(&thread->parent) == RT_Object_Class_Thread);
  140. susp_putter = thread->susp_recycler;
  141. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  142. RT_ASSERT(thread->tid_ref_count > 0);
  143. thread->tid_ref_count -= 1;
  144. if (!thread->tid_ref_count && susp_putter)
  145. {
  146. rt_thread_resume(susp_putter);
  147. }
  148. lwp_mutex_release_safe(&tid_lock);
  149. }
  150. }
  151. void lwp_tid_set_thread(int tid, rt_thread_t thread)
  152. {
  153. struct lwp_avl_struct *p;
  154. lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
  155. p = lwp_avl_find(tid, lwp_tid_root);
  156. if (p)
  157. {
  158. RT_ASSERT(p->data == RT_NULL);
  159. p->data = thread;
  160. }
  161. lwp_mutex_release_safe(&tid_lock);
  162. }