Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* * Copyright (c) 2012-2014 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file measure context switch time between cooperative threads * * This file contains thread (coop) context switch time measurement. * The thread starts two cooperative thread. One thread waits on a semaphore. The other, * after starting, releases a semaphore which enable the first thread to run. * Each thread increases a common global counter and context switch back and * forth by yielding the cpu. When counter reaches the maximal value, threads * stop and the average time of context switch is displayed. */ #include "timestamp.h" #include "utils.h" #include <arch/cpu.h> /* number of context switches */ #define NCTXSWITCH 10000 #ifndef STACKSIZE #define STACKSIZE 512 #endif /* stack used by the fibers */ static K_THREAD_STACK_DEFINE(thread_one_stack, STACKSIZE); static K_THREAD_STACK_DEFINE(thread_two_stack, STACKSIZE); static struct k_thread thread_one_data; static struct k_thread thread_two_data; static u32_t timestamp; /* context switches counter */ static volatile u32_t ctx_switch_counter; /* context switch balancer. Incremented by one thread, decremented by another*/ static volatile int ctx_switch_balancer; K_SEM_DEFINE(sync_sema, 0, 1); /** * * thread_onne * * Fiber makes all the test preparations: registers the interrupt handler, * gets the first timestamp and invokes the software interrupt. * * @return N/A */ static void thread_one(void) { k_sem_take(&sync_sema, K_FOREVER); timestamp = TIME_STAMP_DELTA_GET(0); while (ctx_switch_counter < NCTXSWITCH) { k_yield(); ctx_switch_counter++; ctx_switch_balancer--; } timestamp = TIME_STAMP_DELTA_GET(timestamp); } /** * * @brief Check the time when it gets executed after the semaphore * * Fiber starts, waits on semaphore. When the interrupt handler releases * the semaphore, thread measures the time. * * @return 0 on success */ static void thread_two(void) { k_sem_give(&sync_sema); while (ctx_switch_counter < NCTXSWITCH) { k_yield(); ctx_switch_counter++; ctx_switch_balancer++; } } /** * * @brief The test main function * * @return 0 on success */ int coop_ctx_switch(void) { PRINT_FORMAT(" 6 - Measure average context switch time between threads (coop)"); ctx_switch_counter = 0; ctx_switch_balancer = 0; bench_test_start(); k_thread_create(&thread_one_data, thread_one_stack, STACKSIZE, (k_thread_entry_t) thread_one, NULL, NULL, NULL, 6, 0, K_NO_WAIT); k_thread_create(&thread_two_data, thread_two_stack, STACKSIZE, (k_thread_entry_t) thread_two, NULL, NULL, NULL, 6, 0, K_NO_WAIT); if (ctx_switch_balancer > 3 || ctx_switch_balancer < -3) { PRINT_FORMAT(" Balance is %d. FAILED", ctx_switch_balancer); } else if (bench_test_end() != 0) { error_count++; PRINT_OVERFLOW_ERROR(); } else { PRINT_FORMAT(" Average context switch time is %u tcs = %u" " nsec", timestamp / ctx_switch_counter, SYS_CLOCK_HW_CYCLES_TO_NS_AVG(timestamp, ctx_switch_counter)); } return 0; } |