lwp_tid.c 4.2 KB

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