1 /* stack.c */
2 
3 /*
4  * Copyright (c) 1997-2010, 2013-2014 Wind River Systems, Inc.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include "syskernel.h"
10 
11 struct k_stack  stack_1;
12 struct k_stack  stack_2;
13 
14 stack_data_t stack1[2];
15 stack_data_t stack2[2];
16 
17 /**
18  *
19  * @brief Initialize stacks for the test
20  *
21  */
stack_test_init(void)22 void stack_test_init(void)
23 {
24 	k_stack_init(&stack_1, stack1, 2);
25 	k_stack_init(&stack_2, stack2, 2);
26 }
27 
28 
29 /**
30  *
31  * @brief Stack test thread
32  *
33  * @param par1   Ignored parameter.
34  * @param par2   Number of test loops.
35  * @param par3	 Unused
36  *
37  */
stack_thread1(void * par1,void * par2,void * par3)38 void stack_thread1(void *par1, void *par2, void *par3)
39 {
40 	int num_loops = POINTER_TO_INT(par2) / 2;
41 	int i;
42 	stack_data_t data;
43 
44 	ARG_UNUSED(par1);
45 	ARG_UNUSED(par3);
46 
47 	for (i = 0; i < num_loops; i++) {
48 		k_stack_pop(&stack_1, &data, K_FOREVER);
49 		if (data != 2 * i) {
50 			break;
51 		}
52 		data = 2 * i;
53 		k_stack_push(&stack_2, data);
54 		k_stack_pop(&stack_1, &data, K_FOREVER);
55 		if (data != 2 * i + 1) {
56 			break;
57 		}
58 		data = 2 * i + 1;
59 		k_stack_push(&stack_2, data);
60 	}
61 }
62 
63 
64 /**
65  *
66  * @brief Stack test thread
67  *
68  * @param par1   Address of the counter.
69  * @param par2   Number of test cycles.
70  * @param par3	 Unused
71  *
72  */
stack_thread2(void * par1,void * par2,void * par3)73 void stack_thread2(void *par1, void *par2, void *par3)
74 {
75 	int i;
76 	stack_data_t data;
77 	int *pcounter = par1;
78 	int num_loops = POINTER_TO_INT(par2);
79 
80 	ARG_UNUSED(par3);
81 
82 	for (i = 0; i < num_loops; i++) {
83 		data = i;
84 		k_stack_push(&stack_1, data);
85 		k_stack_pop(&stack_2, &data, K_FOREVER);
86 		if (data != i) {
87 			break;
88 		}
89 		(*pcounter)++;
90 	}
91 }
92 
93 
94 /**
95  *
96  * @brief Stack test thread
97  *
98  * @param par1   Address of the counter.
99  * @param par2   Number of test cycles.
100  * @param par3	 Unused
101  *
102  */
stack_thread3(void * par1,void * par2,void * par3)103 void stack_thread3(void *par1, void *par2, void *par3)
104 {
105 	int i;
106 	stack_data_t data;
107 	int *pcounter = par1;
108 	int num_loops = POINTER_TO_INT(par2);
109 
110 	ARG_UNUSED(par3);
111 
112 	for (i = 0; i < num_loops; i++) {
113 		data = i;
114 		k_stack_push(&stack_1, data);
115 		data = 0xffffffff;
116 
117 		while (k_stack_pop(&stack_2, &data,
118 					     K_NO_WAIT) != 0) {
119 			k_yield();
120 		}
121 		if (data != i) {
122 			break;
123 		}
124 		(*pcounter)++;
125 	}
126 }
127 
128 
129 /**
130  *
131  * @brief The main test entry
132  *
133  * @return 1 if success and 0 on failure
134  *
135  */
stack_test(void)136 int stack_test(void)
137 {
138 	uint32_t t;
139 	int i = 0;
140 	int return_value = 0;
141 
142 	/* test get wait & put stack functions between co-op threads */
143 	fprintf(output_file, sz_test_case_fmt,
144 			"Stack #1");
145 	fprintf(output_file, sz_description,
146 			"\n\tk_stack_init"
147 			"\n\tk_stack_pop(K_FOREVER)"
148 			"\n\tk_stack_push");
149 	printf(sz_test_start_fmt);
150 
151 	stack_test_init();
152 
153 	t = BENCH_START();
154 
155 	k_thread_create(&thread_data1, thread_stack1, STACK_SIZE, stack_thread1,
156 			 0, INT_TO_POINTER(number_of_loops), NULL,
157 			 K_PRIO_COOP(3), 0, K_NO_WAIT);
158 	k_thread_create(&thread_data2, thread_stack2, STACK_SIZE, stack_thread2,
159 			 (void *) &i, INT_TO_POINTER(number_of_loops), NULL,
160 			 K_PRIO_COOP(3), 0, K_NO_WAIT);
161 
162 	t = TIME_STAMP_DELTA_GET(t);
163 
164 	return_value += check_result(i, t);
165 
166 	/* test get/yield & put stack functions between co-op threads */
167 	fprintf(output_file, sz_test_case_fmt,
168 			"Stack #2");
169 	fprintf(output_file, sz_description,
170 			"\n\tk_stack_init"
171 			"\n\tk_stack_pop(K_FOREVER)"
172 			"\n\tk_stack_pop"
173 			"\n\tk_stack_push"
174 			"\n\tk_yield");
175 	printf(sz_test_start_fmt);
176 
177 	stack_test_init();
178 
179 	t = BENCH_START();
180 
181 	i = 0;
182 	k_thread_create(&thread_data1, thread_stack1, STACK_SIZE, stack_thread1,
183 			 0, INT_TO_POINTER(number_of_loops), NULL,
184 			 K_PRIO_COOP(3), 0, K_NO_WAIT);
185 	k_thread_create(&thread_data2, thread_stack2, STACK_SIZE, stack_thread3,
186 			 (void *) &i, INT_TO_POINTER(number_of_loops), NULL,
187 			 K_PRIO_COOP(3), 0, K_NO_WAIT);
188 
189 	t = TIME_STAMP_DELTA_GET(t);
190 
191 	return_value += check_result(i, t);
192 
193 	/* test get wait & put stack functions across co-op and preemptive
194 	 * threads
195 	 */
196 	fprintf(output_file, sz_test_case_fmt,
197 			"Stack #3");
198 	fprintf(output_file, sz_description,
199 			"\n\tk_stack_init"
200 			"\n\tk_stack_pop(K_FOREVER)"
201 			"\n\tk_stack_push"
202 			"\n\tk_stack_pop(K_FOREVER)"
203 			"\n\tk_stack_push");
204 	printf(sz_test_start_fmt);
205 
206 	stack_test_init();
207 
208 	t = BENCH_START();
209 
210 	k_thread_create(&thread_data1, thread_stack1, STACK_SIZE, stack_thread1,
211 			 0, INT_TO_POINTER(number_of_loops), NULL,
212 			 K_PRIO_COOP(3), 0, K_NO_WAIT);
213 
214 	for (i = 0; i < number_of_loops / 2U; i++) {
215 		stack_data_t data;
216 
217 		data = 2 * i;
218 		k_stack_push(&stack_1, data);
219 		data = 2 * i + 1;
220 		k_stack_push(&stack_1, data);
221 
222 		k_stack_pop(&stack_2, &data, K_FOREVER);
223 		if (data != 2 * i + 1) {
224 			break;
225 		}
226 		k_stack_pop(&stack_2, &data, K_FOREVER);
227 		if (data != 2 * i) {
228 			break;
229 		}
230 	}
231 
232 	t = TIME_STAMP_DELTA_GET(t);
233 
234 	return_value += check_result(i * 2, t);
235 
236 	return return_value;
237 }
238