Linux preempt-rt

Check our new training course

Real-Time Linux with PREEMPT_RT

Check our new training course
with Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/* stack.c */

/*
 * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "syskernel.h"

struct k_stack  stack_1;
struct k_stack  stack_2;

stack_data_t stack1[2];
stack_data_t stack2[2];

/**
 *
 * @brief Initialize stacks for the test
 *
 * @return N/A
 *
 */
void stack_test_init(void)
{
	k_stack_init(&stack_1, stack1, 2);
	k_stack_init(&stack_2, stack2, 2);
}


/**
 *
 * @brief Stack test thread
 *
 * @param par1   Ignored parameter.
 * @param par2   Number of test loops.
 * @param par3	 Unused
 *
 * @return N/A
 *
 */
void stack_thread1(void *par1, void *par2, void *par3)
{
	int num_loops = POINTER_TO_INT(par2) / 2;
	int i;
	stack_data_t data;

	ARG_UNUSED(par1);
	ARG_UNUSED(par3);

	for (i = 0; i < num_loops; i++) {
		k_stack_pop(&stack_1, &data, K_FOREVER);
		if (data != 2 * i) {
			break;
		}
		data = 2 * i;
		k_stack_push(&stack_2, data);
		k_stack_pop(&stack_1, &data, K_FOREVER);
		if (data != 2 * i + 1) {
			break;
		}
		data = 2 * i + 1;
		k_stack_push(&stack_2, data);
	}
}


/**
 *
 * @brief Stack test thread
 *
 * @param par1   Address of the counter.
 * @param par2   Number of test cycles.
 * @param par3	 Unused
 *
 * @return N/A
 *
 */
void stack_thread2(void *par1, void *par2, void *par3)
{
	int i;
	stack_data_t data;
	int *pcounter = par1;
	int num_loops = POINTER_TO_INT(par2);

	ARG_UNUSED(par3);

	for (i = 0; i < num_loops; i++) {
		data = i;
		k_stack_push(&stack_1, data);
		k_stack_pop(&stack_2, &data, K_FOREVER);
		if (data != i) {
			break;
		}
		(*pcounter)++;
	}
}


/**
 *
 * @brief Stack test thread
 *
 * @param par1   Address of the counter.
 * @param par2   Number of test cycles.
 * @param par3	 Unused
 *
 * @return N/A
 *
 */
void stack_thread3(void *par1, void *par2, void *par3)
{
	int i;
	stack_data_t data;
	int *pcounter = par1;
	int num_loops = POINTER_TO_INT(par2);

	ARG_UNUSED(par3);

	for (i = 0; i < num_loops; i++) {
		data = i;
		k_stack_push(&stack_1, data);
		data = 0xffffffff;

		while (k_stack_pop(&stack_2, &data,
					     K_NO_WAIT) != 0) {
			k_yield();
		}
		if (data != i) {
			break;
		}
		(*pcounter)++;
	}
}


/**
 *
 * @brief The main test entry
 *
 * @return 1 if success and 0 on failure
 *
 */
int stack_test(void)
{
	u32_t t;
	int i = 0;
	int return_value = 0;

	/* test get wait & put stack functions between co-op threads */
	fprintf(output_file, sz_test_case_fmt,
			"Stack #1");
	fprintf(output_file, sz_description,
			"\n\tk_stack_init"
			"\n\tk_stack_pop(K_FOREVER)"
			"\n\tk_stack_push");
	printf(sz_test_start_fmt);

	stack_test_init();

	t = BENCH_START();

	k_thread_create(&thread_data1, thread_stack1, STACK_SIZE, stack_thread1,
			 0, INT_TO_POINTER(number_of_loops), NULL,
			 K_PRIO_COOP(3), 0, K_NO_WAIT);
	k_thread_create(&thread_data2, thread_stack2, STACK_SIZE, stack_thread2,
			 (void *) &i, INT_TO_POINTER(number_of_loops), NULL,
			 K_PRIO_COOP(3), 0, K_NO_WAIT);

	t = TIME_STAMP_DELTA_GET(t);

	return_value += check_result(i, t);

	/* test get/yield & put stack functions between co-op threads */
	fprintf(output_file, sz_test_case_fmt,
			"Stack #2");
	fprintf(output_file, sz_description,
			"\n\tk_stack_init"
			"\n\tk_stack_pop(K_FOREVER)"
			"\n\tk_stack_pop"
			"\n\tk_stack_push"
			"\n\tk_yield");
	printf(sz_test_start_fmt);

	stack_test_init();

	t = BENCH_START();

	i = 0;
	k_thread_create(&thread_data1, thread_stack1, STACK_SIZE, stack_thread1,
			 0, INT_TO_POINTER(number_of_loops), NULL,
			 K_PRIO_COOP(3), 0, K_NO_WAIT);
	k_thread_create(&thread_data2, thread_stack2, STACK_SIZE, stack_thread3,
			 (void *) &i, INT_TO_POINTER(number_of_loops), NULL,
			 K_PRIO_COOP(3), 0, K_NO_WAIT);

	t = TIME_STAMP_DELTA_GET(t);

	return_value += check_result(i, t);

	/* test get wait & put stack functions across co-op and premptive
	 * threads
	 */
	fprintf(output_file, sz_test_case_fmt,
			"Stack #3");
	fprintf(output_file, sz_description,
			"\n\tk_stack_init"
			"\n\tk_stack_pop(K_FOREVER)"
			"\n\tk_stack_push"
			"\n\tk_stack_pop(K_FOREVER)"
			"\n\tk_stack_push");
	printf(sz_test_start_fmt);

	stack_test_init();

	t = BENCH_START();

	k_thread_create(&thread_data1, thread_stack1, STACK_SIZE, stack_thread1,
			 0, INT_TO_POINTER(number_of_loops), NULL,
			 K_PRIO_COOP(3), 0, K_NO_WAIT);

	for (i = 0; i < number_of_loops / 2U; i++) {
		stack_data_t data;

		data = 2 * i;
		k_stack_push(&stack_1, data);
		data = 2 * i + 1;
		k_stack_push(&stack_1, data);

		k_stack_pop(&stack_2, &data, K_FOREVER);
		if (data != 2 * i + 1) {
			break;
		}
		k_stack_pop(&stack_2, &data, K_FOREVER);
		if (data != 2 * i) {
			break;
		}
	}

	t = TIME_STAMP_DELTA_GET(t);

	return_value += check_result(i * 2, t);

	return return_value;
}