context_switch_tc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-07-03 rcitach test case for context_switch
  9. * 2025-11-30 westcity-YOLO Add standardized utest documentation block
  10. */
  11. /*
  12. * Test Case Name: Kernel Core Context Switch Performance Test
  13. *
  14. * Test Objectives:
  15. * - Measures thread context switch overhead using semaphore synchronization
  16. * - Validates interrupt-to-thread response time in switch scenarios
  17. * - Provides quantitative results in microseconds (us)
  18. *
  19. * Test Scenarios:
  20. * - **Thread Switch Simulation**: Two threads alternate using semaphores
  21. * - **High-Resolution Timing**: Hardware timer measures switch duration
  22. * - **Stress Cycles**: Repeated switch operations (RT_UTEST_SYS_PERF_TC_COUNT times)
  23. * - **Priority Handling**: Higher-priority thread execution (THREAD_PRIORITY+1)
  24. *
  25. * Verification Metrics:
  26. * - Switch time within reasonable limits (< 100 us)
  27. * - Consistent results across multiple test cycles
  28. * - No memory leaks during test execution
  29. * - Correct thread priority handling
  30. *
  31. * Dependencies:
  32. * - RT_USING_PERF_TEST must be enabled
  33. * - RT_USING_UTEST framework must be enabled
  34. * - Hardware timer support (for high-resolution timing)
  35. *
  36. * Expected Results:
  37. * [ PASSED ] [ result ] testcase (core.context_switch)
  38. * - Performance data printed in structured table format
  39. * - Final line: "=== Context Switch Test Results End ==="
  40. * - Test executed via: `utest_run core.context_switch` in msh
  41. */
  42. #include <rtthread.h>
  43. #include <rthw.h>
  44. #include <rtdevice.h>
  45. #include <utest.h>
  46. #include <utest_assert.h>
  47. #include <perf_tc.h>
  48. static rt_sem_t sem1, sem2;
  49. static rt_sem_t complete_sem = RT_NULL;
  50. static void local_modify_time(rt_perf_t *perf)
  51. {
  52. if(perf)
  53. perf->real_time = perf->real_time - perf->tmp_time;
  54. }
  55. static void perf_thread_event1(void *parameter)
  56. {
  57. while (1)
  58. {
  59. rt_sem_take(sem1, RT_WAITING_FOREVER);
  60. rt_sem_release(sem2);
  61. }
  62. }
  63. static void perf_thread_event2(void *parameter)
  64. {
  65. rt_perf_t *perf = (rt_perf_t *)parameter;
  66. for (rt_uint32_t i = 0; i < RT_UTEST_SYS_PERF_TC_COUNT; i++)
  67. {
  68. perf->tmp_time = 0;
  69. rt_perf_start(perf);
  70. rt_sem_take(sem2, RT_WAITING_FOREVER);
  71. rt_sem_release(sem2);
  72. rt_perf_stop(perf);
  73. rt_mutex_take(perf->lock,RT_WAITING_FOREVER);
  74. perf->count -= 1;
  75. perf->tmp_time = perf->real_time;
  76. rt_mutex_release(perf->lock);
  77. rt_perf_start(perf);
  78. rt_sem_take(sem2, RT_WAITING_FOREVER);
  79. rt_sem_release(sem1);
  80. rt_perf_stop(perf);
  81. }
  82. rt_sem_release(complete_sem);
  83. }
  84. rt_err_t context_switch_test(rt_perf_t *perf)
  85. {
  86. rt_thread_t thread1 = RT_NULL;
  87. rt_thread_t thread2 = RT_NULL;
  88. # if __STDC_VERSION__ >= 199901L
  89. rt_strcpy(perf->name,__func__);
  90. #else
  91. rt_strcpy(perf->name,"context_switch_test");
  92. #endif
  93. perf->local_modify = local_modify_time;
  94. sem1 = rt_sem_create("sem1", 1, RT_IPC_FLAG_FIFO);
  95. sem2 = rt_sem_create("sem2", 0, RT_IPC_FLAG_FIFO);
  96. complete_sem = rt_sem_create("complete_sem", 0, RT_IPC_FLAG_FIFO);
  97. thread1 = rt_thread_create("perf_thread_event1", perf_thread_event1, perf,
  98. THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);
  99. if (thread1 == RT_NULL)
  100. {
  101. LOG_E("perf_thread_event1 create failed.");
  102. return -RT_ERROR;
  103. }
  104. thread2 = rt_thread_create("perf_thread_event2", perf_thread_event2, perf,
  105. THREAD_STACK_SIZE, THREAD_PRIORITY + 1, THREAD_TIMESLICE);
  106. if (thread2 == RT_NULL)
  107. {
  108. LOG_E("perf_thread_event2 create failed.");
  109. return -RT_ERROR;
  110. }
  111. rt_thread_startup(thread1);
  112. rt_thread_startup(thread2);
  113. rt_sem_take(complete_sem, RT_WAITING_FOREVER);
  114. rt_perf_dump(perf);
  115. rt_thread_delete(thread1);
  116. rt_sem_delete(complete_sem);
  117. rt_sem_delete(sem1);
  118. rt_sem_delete(sem2);
  119. return RT_EOK;
  120. }