Commit 95a97fd2 authored by Peter Mitsis's avatar Peter Mitsis Committed by Anas Nashif
Browse files

tests: Port Thread-Metric benchmark from ThreadX

Ports the Thread-Metric suite of benchmarks from ThreadX to Zephyr.
This makes it easier for others to run these benchmarks with the
best set of configuration options for their board so that
they can better compare Zephyr performance to another RTOS.

Signed-off-by: default avatarPeter Mitsis <peter.mitsis@intel.com>
parent c9ce311a
Loading
Loading
Loading
Loading
+16 −0
Changes for tests/benchmarks/thread_metric/CMakeLists.txt: 16 added lines, 0 removed lines.
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(thread_metric)

FILE(GLOB app_sources src/tm_porting_layer_zephyr.c)
target_sources(app PRIVATE ${app_sources})
target_sources_ifdef(CONFIG_TM_BASIC                 app PRIVATE src/tm_basic_processing_test.c)
target_sources_ifdef(CONFIG_TM_COOPERATIVE           app PRIVATE src/tm_cooperative_scheduling_test.c)
target_sources_ifdef(CONFIG_TM_INTERRUPT             app PRIVATE src/tm_interrupt_processing_test.c)
target_sources_ifdef(CONFIG_TM_INTERRUPT_PREEMPTION  app PRIVATE src/tm_interrupt_preemption_processing_test.c)
target_sources_ifdef(CONFIG_TM_MEMORY_ALLOCATION     app PRIVATE src/tm_memory_allocation_test.c)
target_sources_ifdef(CONFIG_TM_MESSAGE               app PRIVATE src/tm_message_processing_test.c)
target_sources_ifdef(CONFIG_TM_PREEMPTIVE            app PRIVATE src/tm_preemptive_scheduling_test.c)
target_sources_ifdef(CONFIG_TM_SYNCHRONIZATION       app PRIVATE src/tm_synchronization_processing_test.c)
+83 −0
Changes for tests/benchmarks/thread_metric/Kconfig: 83 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Copyright (c) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

mainmenu "Eclipse ThreadX Thread-Metric RTOS Test Suite"

source "Kconfig.zephyr"

choice TM_TEST
	prompt "Select a Thread-Metric test to execute"
	default TM_PREEMPTIVE
	help
	  The Thread-Metric benchmark suite consists of eight RTOS tests.
	  These tests measure the total number of RTOS events that can be
	  processed during a 30 second time interval.

config TM_BASIC
	bool "Baseline basic benchmark"
	help
	  The baseline basic benchmark consists of a single thread that counts
	  the number of times it performs a set of calculations. This number
	  is reported every 30 seconds.

config TM_COOPERATIVE
	bool "Cooperative context switching"
	help
	  The cooperative context switching benchmark spawns five (5) threads
	  of equal priority that yield to each other and increment counters
	  on each context switch. The sum total of the counters is reported
	  every 30 seconds.

config TM_INTERRUPT
	bool "Interrupt processing"
	select TEST
	select IRQ_OFFLOAD
	select IRQ_OFFLOAD_NESTED
	help
	  The interrupt processing benchmark has a single thread that causes
	  an interrupt which results in its ISR incrementing a counter and then
	  posting a semaphore. The thread then increments its own counter and
	  takes that semaphore. The sum total of the counters is reported
	  every 30 seconds.

config TM_INTERRUPT_PREEMPTION
	bool "Interrupt processing preemption"
	select TEST
	select IRQ_OFFLOAD
	select IRQ_OFFLOAD_NESTED
	help
	  The interrupt preemption benchmark counts the number of times that
	  an ISR from a software generated interrupt results in the preemption
	  of a thread. The total number of context switches is reported every
	  30 seconds.

config TM_MEMORY_ALLOCATION
	bool "Memory allocation"
	help
	  The memory allocation benchmark counts the number of times a thread
	  is able to allocate and then release a 128-byte block. This number
	  is reported every 30 seconds.

config TM_MESSAGE
	bool "Message processing"
	help
	  The message processing benchmark counts the number of times that a
	  thread can send and receive a 16-byte message from a message queue.
	  This number is reported every 30 seconds.

config TM_PREEMPTIVE
	bool "Preemptive context switching"
	help
	  The preemptive context switching benchmark creates five (5) threads
	  of different priorities that suspend and resume each other in a
	  cyclical pattern. The total number of context switches is reported
	  every 30 seconds.

config TM_SYNCHRONIZATION
	bool "Synchronization"
	help
	  The synchronization benchmark counts the number of times that a
	  thread can give and take a semaphore without blocking. This number
	  is reported every 30 seconds.

endchoice
+25 −0
Changes for tests/benchmarks/thread_metric/prj.conf: 25 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Default base configuration file

# Use a tickless kernel to minimize the number of timer interrupts
CONFIG_TICKLESS_KERNEL=y
CONFIG_SYS_CLOCK_TICKS_PER_SEC=100

# Optimize for speed
CONFIG_SPEED_OPTIMIZATIONS=y

# Disable time slicing
CONFIG_TIMESLICING=n

# Test is only designed for a single CPU
CONFIG_MP_MAX_NUM_CPUS=1

# Disabling hardware stack protection can greatly
# improve system performance.
CONFIG_HW_STACK_PROTECTION=n

# Picolibc is faster than Zephyr's minimal libc memcpy
CONFIG_PICOLIBC_SPEED_OPTIMIZATIONS=y
CONFIG_PICOLIBC_USE_MODULE=y

# Disable Thread Local Storage for better context switching times
CONFIG_THREAD_LOCAL_STORAGE=n
+103 −0
Changes for tests/benchmarks/thread_metric/src/tm_api.h: 103 added lines, 0 removed lines.
Original line number Diff line number Diff line
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/

/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** Thread-Metric Component                                               */
/**                                                                       */
/** Application Interface (API)                                           */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

/**************************************************************************/
/*                                                                        */
/*  APPLICATION INTERFACE DEFINITION                       RELEASE        */
/*                                                                        */
/*    tm_api.h                                            PORTABLE C      */
/*                                                           6.1.7        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This file defines the basic Application Interface (API)             */
/*    implementation source code for the Thread-Metrics performance       */
/*    test suite. All service prototypes and data structure definitions   */
/*    are defined in this file.                                           */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  10-15-2021     William E. Lamie         Initial Version 6.1.7         */
/*                                                                        */
/**************************************************************************/

#ifndef TM_API_H
#define TM_API_H

#include "tm_porting_layer.h"

/*
 * Determine if a C++ compiler is being used.  If so, ensure that standard
 * C is used to process the API information.
 */

#ifdef __cplusplus

/* Yes, C++ compiler is present.  Use standard C.  */
extern "C" {

#endif

/* Define API constants.  */

#define TM_SUCCESS 0
#define TM_ERROR   1

/* Define the time interval in seconds. This can be changed with a -D compiler option.  */

#ifndef TM_TEST_DURATION
#define TM_TEST_DURATION 30
#endif

/*
 * Define RTOS Neutral APIs. RTOS vendors should fill in the guts of the following
 * API. Once this is done the Thread-Metric tests can be successfully run.
 */

void tm_initialize(void (*test_initialization_function)(void));
int tm_thread_create(int thread_id, int priority, void (*entry_function)(void *, void *, void *));
int tm_thread_resume(int thread_id);
int tm_thread_suspend(int thread_id);
void tm_thread_relinquish(void);
void tm_thread_sleep(int seconds);
int tm_queue_create(int queue_id);
int tm_queue_send(int queue_id, unsigned long *message_ptr);
int tm_queue_receive(int queue_id, unsigned long *message_ptr);
int tm_semaphore_create(int semaphore_id);
int tm_semaphore_get(int semaphore_id);
int tm_semaphore_put(int semaphore_id);
int tm_memory_pool_create(int pool_id);
int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr);
int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr);

/*
 * Determine if a C++ compiler is being used.  If so, complete the standard
 * C conditional started above.
 */
#ifdef __cplusplus
}
#endif

#endif
+169 −0
Changes for tests/benchmarks/thread_metric/src/tm_basic_processing_test.c: 169 added lines, 0 removed lines.
Original line number Diff line number Diff line
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/

/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** Thread-Metric Component                                               */
/**                                                                       */
/**   Basic Processing Test                                               */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    tm_basic_processing_test                            PORTABLE C      */
/*                                                           6.1.7        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This file defines the basic test for determining board processing   */
/*    capabilities                                                        */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  10-15-2021     William E. Lamie         Initial Version 6.1.7         */
/*                                                                        */
/**************************************************************************/
#include "tm_api.h"

/* Define the counters used in the demo application...  */

volatile unsigned long tm_basic_processing_counter;

/*
 * Test array.  We will just do a series of calculations on the
 * test array to eat up processing bandwidth. The idea is that
 * all RTOSes should produce the same metric here if everything
 * else is equal, e.g. processor speed, memory speed, etc.
 */

volatile unsigned long tm_basic_processing_array[1024];

/* Define the test thread prototypes.  */

void tm_basic_processing_thread_0_entry(void *p1, void *p2, void *p3);

/* Define the reporting function prototype.  */

void tm_basic_processing_thread_report(void);

/* Define the initialization prototype.  */

void tm_basic_processing_initialize(void);

/* Define main entry point.  */

int main(void)
{
	/* Initialize the test.  */
	tm_initialize(tm_basic_processing_initialize);

	return 0;
}

/* Define the basic processing test initialization.  */

void tm_basic_processing_initialize(void)
{
	/* Create thread 0 at priority 10.  */
	tm_thread_create(0, 10, tm_basic_processing_thread_0_entry);

	/* Resume thread 0.  */
	tm_thread_resume(0);

	tm_basic_processing_thread_report();
}

/* Define the basic processing thread.  */
void tm_basic_processing_thread_0_entry(void *p1, void *p2, void *p3)
{
	int i;

	(void)p1;
	(void)p2;
	(void)p3;

	/* Initialize the test array.   */
	for (i = 0; i < 1024; i++) {

		/* Clear the basic processing array.  */
		tm_basic_processing_array[i] = 0;
	}

	while (1) {

		/*
		 * Loop through the basic processing array, add the previous
		 * contents with the contents of the tm_basic_processing_counter
		 * and xor the result with the previous value...   just to eat
		 * up some time.
		 */

		for (i = 0; i < 1024; i++) {

			/* Update each array entry.  */
			tm_basic_processing_array[i] =
				(tm_basic_processing_array[i] + tm_basic_processing_counter) ^
				tm_basic_processing_array[i];
		}

		/* Increment the basic processing counter.  */
		tm_basic_processing_counter++;
	}
}

/* Define the basic processing reporting function.  */
void tm_basic_processing_thread_report(void)
{

	unsigned long last_counter;
	unsigned long relative_time;

	/* Initialize the last counter.  */
	last_counter = 0;

	/* Initialize the relative time.  */
	relative_time = 0;

	while (1) {

		/* Sleep to allow the test to run.  */
		tm_thread_sleep(TM_TEST_DURATION);

		/* Increment the relative time.  */
		relative_time = relative_time + TM_TEST_DURATION;

		/* Print results to the stdio window.  */
		printf("**** Thread-Metric Basic Single Thread Processing Test **** Relative Time: "
		       "%lu\n",
		       relative_time);

		/* See if there are any errors.  */
		if (tm_basic_processing_counter == last_counter) {

			printf("ERROR: Invalid counter value(s). Basic processing thread died!\n");
		}

		/* Show the time period total.  */
		printf("Time Period Total:  %lu\n\n", tm_basic_processing_counter - last_counter);

		/* Save the last counter.  */
		last_counter = tm_basic_processing_counter;
	}
}
Loading