priority_inversion.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. * 2018-08-24 yangjie the first version
  9. */
  10. /*
  11. * 程序清单:使用互斥量来防止优先级反转
  12. *
  13. * 这个例子将创建 3 个动态线程以检查持有互斥量时,持有的线程优先级是否
  14. * 被调整到等待线程优先级中的最高优先级。
  15. *
  16. * 线程 1,2,3 的优先级从高到低分别被创建,
  17. * 线程 3 先持有互斥量,而后线程 2 试图持有互斥量,此时线程 3 的优先级应该
  18. * 被提升为和线程 2 的优先级相同。线程 1 用于检查线程 3 的优先级是否被提升
  19. * 为与线程 2的优先级相同。
  20. */
  21. #include <rtthread.h>
  22. /* 指向线程控制块的指针 */
  23. static rt_thread_t tid1 = RT_NULL;
  24. static rt_thread_t tid2 = RT_NULL;
  25. static rt_thread_t tid3 = RT_NULL;
  26. static rt_mutex_t mutex = RT_NULL;
  27. #define THREAD_PRIORITY 10
  28. #define THREAD_STACK_SIZE 512
  29. #define THREAD_TIMESLICE 5
  30. /* 线程 1 入口 */
  31. static void thread1_entry(void *parameter)
  32. {
  33. /* 先让低优先级线程运行 */
  34. rt_thread_mdelay(100);
  35. /* 此时 thread3 持有 mutex,并且 thread2 等待持有 mutex */
  36. #if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 1, 0))
  37. /* 检查 thread2 与 thread3 的优先级情况 */
  38. if (RT_SCHED_PRIV(tid2).current_priority != RT_SCHED_PRIV(tid3).current_priority)
  39. {
  40. /* 优先级不相同,测试失败 */
  41. rt_kprintf("the priority of thread2 is: %d\n", RT_SCHED_PRIV(tid2).current_priority);
  42. rt_kprintf("the priority of thread3 is: %d\n", RT_SCHED_PRIV(tid3).current_priority);
  43. rt_kprintf("test failed.\n");
  44. return;
  45. }
  46. else
  47. {
  48. rt_kprintf("the priority of thread2 is: %d\n", RT_SCHED_PRIV(tid2).current_priority);
  49. rt_kprintf("the priority of thread3 is: %d\n", RT_SCHED_PRIV(tid3).current_priority);
  50. rt_kprintf("test OK.\n");
  51. }
  52. #else
  53. if (tid2->current_priority != tid3->current_priority)
  54. {
  55. /* 优先级不相同,测试失败 */
  56. rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
  57. rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
  58. rt_kprintf("test failed.\n");
  59. return;
  60. }
  61. else
  62. {
  63. rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
  64. rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
  65. rt_kprintf("test OK.\n");
  66. }
  67. #endif
  68. }
  69. /* 线程 2 入口 */
  70. static void thread2_entry(void *parameter)
  71. {
  72. rt_err_t result;
  73. #if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 1, 0))
  74. rt_kprintf("the priority of thread2 is: %d\n", RT_SCHED_PRIV(tid2).current_priority);
  75. #else
  76. rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
  77. #endif
  78. /* 先让低优先级线程运行 */
  79. rt_thread_mdelay(50);
  80. /*
  81. * 试图持有互斥锁,此时 thread3 持有,应把 thread3 的优先级提升
  82. * 到 thread2 相同的优先级
  83. */
  84. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  85. if (result == RT_EOK)
  86. {
  87. /* 释放互斥锁 */
  88. rt_mutex_release(mutex);
  89. }
  90. }
  91. /* 线程 3 入口 */
  92. static void thread3_entry(void *parameter)
  93. {
  94. rt_tick_t tick;
  95. rt_err_t result;
  96. #if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 1, 0))
  97. rt_kprintf("the priority of thread3 is: %d\n", RT_SCHED_PRIV(tid3).current_priority);
  98. #else
  99. rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
  100. #endif
  101. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  102. if (result != RT_EOK)
  103. {
  104. rt_kprintf("thread3 take a mutex, failed.\n");
  105. }
  106. /* 做一个长时间的循环,500ms */
  107. tick = rt_tick_get();
  108. while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2)) ;
  109. rt_mutex_release(mutex);
  110. }
  111. int pri_inversion(void)
  112. {
  113. /* 创建互斥锁 */
  114. mutex = rt_mutex_create("mutex", RT_IPC_FLAG_PRIO);
  115. if (mutex == RT_NULL)
  116. {
  117. rt_kprintf("create dynamic mutex failed.\n");
  118. return -1;
  119. }
  120. /* 创建线程 1 */
  121. tid1 = rt_thread_create("thread1",
  122. thread1_entry,
  123. RT_NULL,
  124. THREAD_STACK_SIZE,
  125. THREAD_PRIORITY - 1, THREAD_TIMESLICE);
  126. #ifdef RT_USING_SMP
  127. /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */
  128. rt_thread_control(tid1, RT_THREAD_CTRL_BIND_CPU, (void*)0);
  129. #endif
  130. if (tid1 != RT_NULL)
  131. rt_thread_startup(tid1);
  132. /* 创建线程 2 */
  133. tid2 = rt_thread_create("thread2",
  134. thread2_entry,
  135. RT_NULL,
  136. THREAD_STACK_SIZE,
  137. THREAD_PRIORITY, THREAD_TIMESLICE);
  138. #ifdef RT_USING_SMP
  139. /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */
  140. rt_thread_control(tid2, RT_THREAD_CTRL_BIND_CPU, (void*)0);
  141. #endif
  142. if (tid2 != RT_NULL)
  143. rt_thread_startup(tid2);
  144. /* 创建线程 3 */
  145. tid3 = rt_thread_create("thread3",
  146. thread3_entry,
  147. RT_NULL,
  148. THREAD_STACK_SIZE,
  149. THREAD_PRIORITY + 1, THREAD_TIMESLICE);
  150. #ifdef RT_USING_SMP
  151. /* 绑定线程到同一个核上,避免启用多核时的输出混乱 */
  152. rt_thread_control(tid3, RT_THREAD_CTRL_BIND_CPU, (void*)0);
  153. #endif
  154. if (tid3 != RT_NULL)
  155. rt_thread_startup(tid3);
  156. return 0;
  157. }
  158. /* 导出到 msh 命令列表中 */
  159. MSH_CMD_EXPORT(pri_inversion, pri_inversion sample);