2015-04-10 16:44:37 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
|
|
|
|
2017-03-24 10:23:40 -04:00
|
|
|
/**
|
|
|
|
* @file
|
2015-04-10 16:44:37 -07:00
|
|
|
* This file contains the benchmark that measure the average time it takes to
|
2017-03-24 10:23:40 -04:00
|
|
|
* do context switches between threads using k_yield () to force
|
2015-04-10 16:44:37 -07:00
|
|
|
* context switch.
|
|
|
|
*/
|
|
|
|
|
2022-05-06 10:44:33 +02:00
|
|
|
#include <zephyr/zephyr.h>
|
|
|
|
#include <zephyr/timing/timing.h>
|
2018-01-24 07:42:00 -06:00
|
|
|
#include <stdlib.h>
|
2020-04-07 12:21:46 -07:00
|
|
|
#include "timestamp.h"
|
2020-08-18 08:41:02 -04:00
|
|
|
#include "utils.h" /* PRINT () and other macros */
|
2015-04-10 16:44:37 -07:00
|
|
|
|
|
|
|
/* context switch enough time so our measurement is precise */
|
2020-08-18 08:41:02 -04:00
|
|
|
#define NB_OF_YIELD 1000
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2020-05-27 11:26:57 -05:00
|
|
|
static uint32_t helper_thread_iterations;
|
2017-03-24 10:23:40 -04:00
|
|
|
|
2022-02-17 17:09:09 +01:00
|
|
|
#define Y_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
|
2020-08-18 08:41:02 -04:00
|
|
|
#define Y_PRIORITY K_PRIO_PREEMPT(10)
|
2017-03-24 10:23:40 -04:00
|
|
|
|
2017-06-02 14:08:22 -07:00
|
|
|
K_THREAD_STACK_DEFINE(y_stack_area, Y_STACK_SIZE);
|
2017-05-09 14:10:52 -07:00
|
|
|
static struct k_thread y_thread;
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-07-01 17:22:39 -04:00
|
|
|
/**
|
2017-06-16 17:51:40 -07:00
|
|
|
* @brief Helper thread for measuring thread switch latency using yield
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
2017-03-24 10:23:40 -04:00
|
|
|
void yielding_thread(void *arg1, void *arg2, void *arg3)
|
2015-05-14 16:30:48 -05:00
|
|
|
{
|
2017-03-24 10:23:40 -04:00
|
|
|
while (helper_thread_iterations < NB_OF_YIELD) {
|
|
|
|
k_yield();
|
|
|
|
helper_thread_iterations++;
|
2015-05-11 10:16:29 -05:00
|
|
|
}
|
2015-05-14 16:30:48 -05:00
|
|
|
}
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-07-01 17:22:39 -04:00
|
|
|
/**
|
2017-03-24 10:23:40 -04:00
|
|
|
* @brief Entry point for thread context switch using yield test
|
2015-04-10 16:44:37 -07:00
|
|
|
*/
|
2017-03-24 10:23:40 -04:00
|
|
|
void thread_switch_yield(void)
|
2015-05-14 16:30:48 -05:00
|
|
|
{
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t iterations = 0U;
|
|
|
|
int32_t delta;
|
2020-08-18 08:41:02 -04:00
|
|
|
timing_t timestamp_start;
|
|
|
|
timing_t timestamp_end;
|
2020-05-27 11:26:57 -05:00
|
|
|
uint32_t ts_diff;
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2020-08-18 08:41:02 -04:00
|
|
|
timing_start();
|
2015-05-12 10:12:36 -05:00
|
|
|
bench_test_start();
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2020-08-18 08:41:02 -04:00
|
|
|
/* launch helper thread of the same priority as the thread
|
|
|
|
* of routine
|
|
|
|
*/
|
|
|
|
k_thread_create(&y_thread, y_stack_area, Y_STACK_SIZE, yielding_thread,
|
|
|
|
NULL, NULL, NULL, Y_PRIORITY, 0, K_NO_WAIT);
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-05-14 16:30:48 -05:00
|
|
|
/* get initial timestamp */
|
2020-08-18 08:41:02 -04:00
|
|
|
timestamp_start = timing_counter_get();
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2015-05-14 16:30:48 -05:00
|
|
|
/* loop until either helper or this routine reaches number of yields */
|
2016-11-01 17:05:18 -04:00
|
|
|
while (iterations < NB_OF_YIELD &&
|
2017-03-24 10:23:40 -04:00
|
|
|
helper_thread_iterations < NB_OF_YIELD) {
|
|
|
|
k_yield();
|
2015-05-14 16:30:48 -05:00
|
|
|
iterations++;
|
2015-04-10 16:44:37 -07:00
|
|
|
}
|
|
|
|
|
2015-05-14 16:30:48 -05:00
|
|
|
/* get the number of cycles it took to do the test */
|
2020-08-18 08:41:02 -04:00
|
|
|
timestamp_end = timing_counter_get();
|
2015-04-10 16:44:37 -07:00
|
|
|
|
2016-11-01 17:05:18 -04:00
|
|
|
/* Ensure both helper and this routine were context switching back &
|
|
|
|
* forth.
|
2015-05-14 16:30:48 -05:00
|
|
|
* For execution to reach the line below, either this routine or helper
|
|
|
|
* routine reached NB_OF_YIELD. The other loop must be at most one
|
2016-11-01 17:05:18 -04:00
|
|
|
* iteration away from reaching NB_OF_YIELD if execute was switching
|
|
|
|
* back and forth.
|
2015-05-14 16:30:48 -05:00
|
|
|
*/
|
2017-03-24 10:23:40 -04:00
|
|
|
delta = iterations - helper_thread_iterations;
|
2015-05-12 10:43:08 -05:00
|
|
|
if (bench_test_end() < 0) {
|
2017-03-24 10:23:40 -04:00
|
|
|
error_count++;
|
2015-05-14 16:30:48 -05:00
|
|
|
PRINT_OVERFLOW_ERROR();
|
2015-05-15 12:05:47 -05:00
|
|
|
} else if (abs(delta) > 1) {
|
2015-05-14 16:30:48 -05:00
|
|
|
/* expecting even alternating context switch, seems one routine
|
|
|
|
* called yield without the other having chance to execute
|
|
|
|
*/
|
2017-03-24 10:23:40 -04:00
|
|
|
error_count++;
|
2020-08-18 08:41:02 -04:00
|
|
|
printk(" Error, iteration:%u, helper iteration:%u",
|
2017-03-24 10:23:40 -04:00
|
|
|
iterations, helper_thread_iterations);
|
2015-05-15 12:05:47 -05:00
|
|
|
} else {
|
2017-03-24 10:23:40 -04:00
|
|
|
/* thread_yield is called (iterations + helper_thread_iterations)
|
2015-05-14 16:30:48 -05:00
|
|
|
* times in total.
|
|
|
|
*/
|
2020-08-18 08:41:02 -04:00
|
|
|
ts_diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
|
|
|
PRINT_STATS_AVG("Average thread context switch using yield", ts_diff, (iterations + helper_thread_iterations));
|
2015-05-11 10:16:29 -05:00
|
|
|
}
|
2020-04-07 12:21:46 -07:00
|
|
|
|
2020-08-18 08:41:02 -04:00
|
|
|
timing_stop();
|
2015-05-14 16:30:48 -05:00
|
|
|
}
|