priority_inversion.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2006-2018, 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. * 2020-10-17 Meco Man translate to English comment
  10. */
  11. /*
  12. * Demo: prevent priority inversions
  13. *
  14. * This demo creates 3 threads and 1 mutex to
  15. * demonstrate how the mutex prevents priority inversions.
  16. *
  17. * read more:
  18. * https://www.rt-thread.io/document/site/thread-sync/thread-sync/#mutex
  19. */
  20. #include <rtthread.h>
  21. /* thread(s) handler */
  22. static rt_thread_t tid1 = RT_NULL;
  23. static rt_thread_t tid2 = RT_NULL;
  24. static rt_thread_t tid3 = RT_NULL;
  25. static rt_mutex_t mutex = RT_NULL;
  26. #define THREAD_PRIORITY 10
  27. #define THREAD_STACK_SIZE 512
  28. #define THREAD_TIMESLICE 5
  29. /* thread #1 entry function */
  30. static void thread1_entry(void *parameter)
  31. {
  32. /* let the lower priority thread run first */
  33. rt_thread_mdelay(100);
  34. /* at this point, thread #3 holds the mutex and thread #2 is pending on holding the mutex */
  35. /* check the priority level of thread #2 and thread #3 */
  36. if (tid2->current_priority != tid3->current_priority)
  37. {
  38. /* failure */
  39. rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
  40. rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
  41. rt_kprintf("test failed.\n");
  42. return;
  43. }
  44. else
  45. {
  46. rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
  47. rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
  48. rt_kprintf("test OK.\n");
  49. }
  50. }
  51. /* thread #2 entry function */
  52. static void thread2_entry(void *parameter)
  53. {
  54. rt_err_t result;
  55. rt_kprintf("the priority of thread2 is: %d\n", tid2->current_priority);
  56. /* let the lower priority thread run first */
  57. rt_thread_mdelay(50);
  58. /*
  59. * pending the mutex
  60. * At this time, kernel raises the priority of thread #3 to same priority
  61. * as thread #2
  62. */
  63. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  64. if (result == RT_EOK)
  65. {
  66. /* release the mutex */
  67. rt_mutex_release(mutex);
  68. }
  69. }
  70. /* thread #3 entry function */
  71. static void thread3_entry(void *parameter)
  72. {
  73. rt_tick_t tick;
  74. rt_err_t result;
  75. rt_kprintf("the priority of thread3 is: %d\n", tid3->current_priority);
  76. result = rt_mutex_take(mutex, RT_WAITING_FOREVER);
  77. if (result != RT_EOK)
  78. {
  79. rt_kprintf("thread3 take a mutex, failed.\n");
  80. }
  81. /* delay for 500ms without scheduling */
  82. tick = rt_tick_get();
  83. while (rt_tick_get() - tick < (RT_TICK_PER_SECOND / 2)) ;
  84. /* release the mutex */
  85. rt_mutex_release(mutex);
  86. }
  87. int pri_inversion(void)
  88. {
  89. /* create mutex */
  90. mutex = rt_mutex_create("mutex", RT_IPC_FLAG_FIFO);
  91. if (mutex == RT_NULL)
  92. {
  93. rt_kprintf("create dynamic mutex failed.\n");
  94. return -1;
  95. }
  96. /* create thread #1 */
  97. tid1 = rt_thread_create("thread1",
  98. thread1_entry,
  99. RT_NULL,
  100. THREAD_STACK_SIZE,
  101. THREAD_PRIORITY - 1, THREAD_TIMESLICE);
  102. if (tid1 != RT_NULL)
  103. rt_thread_startup(tid1);
  104. /* create thread #2 */
  105. tid2 = rt_thread_create("thread2",
  106. thread2_entry,
  107. RT_NULL,
  108. THREAD_STACK_SIZE,
  109. THREAD_PRIORITY, THREAD_TIMESLICE);
  110. if (tid2 != RT_NULL)
  111. rt_thread_startup(tid2);
  112. /* create thread #3 */
  113. tid3 = rt_thread_create("thread3",
  114. thread3_entry,
  115. RT_NULL,
  116. THREAD_STACK_SIZE,
  117. THREAD_PRIORITY + 1, THREAD_TIMESLICE);
  118. if (tid3 != RT_NULL)
  119. rt_thread_startup(tid3);
  120. return 0;
  121. }
  122. /* export the msh command */
  123. MSH_CMD_EXPORT(pri_inversion, pri_inversion sample);