lwp_internal.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-07-25 Shell first version
  9. * 2023-11-25 Shell Add pgrp, session lock API
  10. */
  11. #define DBG_TAG "lwp.internal"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #include <stdlib.h>
  15. #include "lwp_internal.h"
  16. static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags)
  17. {
  18. LWP_DEF_RETURN_CODE(rc);
  19. int retry;
  20. rt_int32_t effect_timeout;
  21. #ifdef LWP_DEBUG
  22. rt_thread_t thread = rt_thread_self();
  23. #endif
  24. if (mtx)
  25. {
  26. effect_timeout = timeout;
  27. #if DBG_LVL == DBG_LOG && defined(LWP_DEBUG)
  28. int exception;
  29. rt_list_t *node = RT_NULL;
  30. struct rt_mutex *tak_obj = RT_NULL;
  31. if (!rt_list_isempty(&(thread->taken_object_list)) && timeout == RT_WAITING_FOREVER)
  32. {
  33. exception = 1;
  34. effect_timeout = 0;
  35. }
  36. else
  37. {
  38. exception = 0;
  39. }
  40. #endif /* DBG_LOG && defined(LWP_DEBUG) */
  41. do {
  42. retry = 0;
  43. if (flags & LWP_MTX_FLAGS_INTR)
  44. rc = rt_mutex_take_interruptible(mtx, effect_timeout);
  45. else
  46. rc = rt_mutex_take_killable(mtx, effect_timeout);
  47. #ifdef LWP_DEBUG
  48. if (rc == RT_EOK)
  49. {
  50. if (!(flags & LWP_MTX_FALGS_NESTED) && rt_mutex_get_hold(mtx) > 1)
  51. {
  52. LOG_W("Already hold the lock");
  53. rt_backtrace();
  54. }
  55. }
  56. else if (rc == -RT_ETIMEOUT)
  57. {
  58. #if DBG_LVL == DBG_LOG
  59. if (exception)
  60. {
  61. rt_list_for_each(node, &(thread->taken_object_list))
  62. {
  63. tak_obj = rt_list_entry(node, struct rt_mutex, taken_list);
  64. if (rt_mutex_get_owner(tak_obj)->stat & RT_THREAD_SUSPEND_MASK)
  65. LOG_D("Potential dead lock - Taken: %s, Try take: %s",
  66. tak_obj->parent.parent.name, mtx->parent.parent.name);
  67. }
  68. rt_backtrace();
  69. retry = 1;
  70. exception = 0;
  71. }
  72. #endif
  73. }
  74. else if (rc != -RT_EINTR)
  75. {
  76. char tname[RT_NAME_MAX];
  77. rt_thread_get_name(thread, tname, sizeof(tname));
  78. LOG_W("Possible kernel corruption detected on thread %s with errno %ld", tname, rc);
  79. }
  80. #endif /* LWP_DEBUG */
  81. } while (retry);
  82. }
  83. else
  84. {
  85. rc = -RT_ERROR;
  86. LOG_W("%s: mtx should not be NULL", __func__);
  87. RT_ASSERT(0);
  88. }
  89. LWP_RETURN(rc);
  90. }
  91. rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags)
  92. {
  93. LWP_DEF_RETURN_CODE(rc);
  94. rc = _mutex_take_safe(mtx, timeout, flags);
  95. LWP_RETURN(rc);
  96. }
  97. rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx)
  98. {
  99. LWP_DEF_RETURN_CODE(rc);
  100. rc = rt_mutex_release(mtx);
  101. if (rc)
  102. {
  103. LOG_I("%s: release failed with code %ld", __func__, rc);
  104. rt_backtrace();
  105. }
  106. LWP_RETURN(rc);
  107. }
  108. rt_err_t lwp_critical_enter(struct rt_lwp *lwp, int flags)
  109. {
  110. rt_err_t rc;
  111. do {
  112. rc = lwp_mutex_take_safe(&lwp->lwp_lock, RT_WAITING_FOREVER, flags);
  113. } while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
  114. /* if current process is force killed */
  115. if (rc != RT_EOK && rc != -RT_EINTR)
  116. {
  117. LOG_I("%s: unexpected return code = %ld", __func__, rc);
  118. }
  119. return rc;
  120. }
  121. rt_err_t lwp_critical_exit(struct rt_lwp *lwp)
  122. {
  123. return lwp_mutex_release_safe(&lwp->lwp_lock);
  124. }
  125. rt_err_t lwp_pgrp_critical_enter(struct rt_processgroup *pgrp, int flags)
  126. {
  127. rt_err_t rc;
  128. do {
  129. rc = lwp_mutex_take_safe(&pgrp->mutex, RT_WAITING_FOREVER, flags);
  130. } while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
  131. /* if current process is force killed */
  132. if (rc != RT_EOK && rc != -RT_EINTR)
  133. {
  134. LOG_I("%s: unexpected return code = %ld", __func__, rc);
  135. }
  136. return rc;
  137. }
  138. rt_err_t lwp_pgrp_critical_exit(struct rt_processgroup *pgrp)
  139. {
  140. return lwp_mutex_release_safe(&pgrp->mutex);
  141. }
  142. rt_err_t lwp_sess_critical_enter(struct rt_session *sess, int flags)
  143. {
  144. rt_err_t rc;
  145. do {
  146. rc = lwp_mutex_take_safe(&sess->mutex, RT_WAITING_FOREVER, flags);
  147. } while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
  148. /* if current process is force killed */
  149. if (rc != RT_EOK && rc != -RT_EINTR)
  150. {
  151. LOG_I("%s: unexpected return code = %ld", __func__, rc);
  152. }
  153. return rc;
  154. }
  155. rt_err_t lwp_sess_critical_exit(struct rt_session *sess)
  156. {
  157. return lwp_mutex_release_safe(&sess->mutex);
  158. }