Skip to content

Commit c2d2cf6

Browse files
peter-mitsisaescolar
authored andcommitted
tests: latency_measure: Add LIFO support
Adds LIFO support to the latency_measure benchmark test. This covers both k_lifo_put() and k_lifo_get() with and without context switches as well as variations for userspace support. Signed-off-by: Peter Mitsis <[email protected]>
1 parent 911182c commit c2d2cf6

File tree

2 files changed

+346
-1
lines changed

2 files changed

+346
-1
lines changed
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
/*
2+
* Copyright (c) 2024 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/*
8+
* @file measure time for various LIFO operations
9+
*
10+
* This file contains the tests that measures the times for the following
11+
* LIFO operations from both kernel threads and user threads:
12+
* 1. Immediately adding a data item to a LIFO
13+
* 2. Immediately removing a data item from a LIFO
14+
* 3. Immediately adding a data item to a LIFO with allocation
15+
* 4. Immediately removing a data item from a LIFO with allocation
16+
* 5. Blocking on removing a data item from a LIFO
17+
* 6. Waking (and context switching to) a thread blocked on a LIFO via
18+
* k_lifo_put().
19+
* 7. Waking (and context switching to) a thread blocked on a LIFO via
20+
* k_lifo_alloc_put().
21+
*/
22+
23+
#include <zephyr/kernel.h>
24+
#include <zephyr/timing/timing.h>
25+
#include "utils.h"
26+
#include "timing_sc.h"
27+
28+
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
29+
30+
static K_LIFO_DEFINE(lifo);
31+
32+
BENCH_BMEM uintptr_t lifo_data[5];
33+
34+
static void lifo_put_get_thread_entry(void *p1, void *p2, void *p3)
35+
{
36+
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
37+
uint32_t options = (uint32_t)(uintptr_t)p2;
38+
timing_t start;
39+
timing_t mid;
40+
timing_t finish;
41+
uint64_t put_sum = 0ULL;
42+
uint64_t get_sum = 0ULL;
43+
uintptr_t *data;
44+
45+
if ((options & K_USER) == 0) {
46+
for (uint32_t i = 0; i < num_iterations; i++) {
47+
start = timing_timestamp_get();
48+
49+
k_lifo_put(&lifo, lifo_data);
50+
51+
mid = timing_timestamp_get();
52+
53+
data = k_lifo_get(&lifo, K_NO_WAIT);
54+
55+
finish = timing_timestamp_get();
56+
57+
put_sum += timing_cycles_get(&start, &mid);
58+
get_sum += timing_cycles_get(&mid, &finish);
59+
}
60+
61+
timestamp.cycles = put_sum;
62+
k_sem_take(&pause_sem, K_FOREVER);
63+
64+
timestamp.cycles = get_sum;
65+
k_sem_take(&pause_sem, K_FOREVER);
66+
67+
put_sum = 0ULL;
68+
get_sum = 0ULL;
69+
}
70+
71+
for (uint32_t i = 0; i < num_iterations; i++) {
72+
start = timing_timestamp_get();
73+
74+
k_lifo_alloc_put(&lifo, lifo_data);
75+
76+
mid = timing_timestamp_get();
77+
78+
data = k_lifo_get(&lifo, K_NO_WAIT);
79+
80+
finish = timing_timestamp_get();
81+
82+
put_sum += timing_cycles_get(&start, &mid);
83+
get_sum += timing_cycles_get(&mid, &finish);
84+
}
85+
86+
timestamp.cycles = put_sum;
87+
k_sem_take(&pause_sem, K_FOREVER);
88+
89+
timestamp.cycles = get_sum;
90+
}
91+
92+
int lifo_ops(uint32_t num_iterations, uint32_t options)
93+
{
94+
int priority;
95+
uint64_t cycles;
96+
char description[80];
97+
98+
priority = k_thread_priority_get(k_current_get());
99+
100+
timing_start();
101+
102+
k_thread_create(&start_thread, start_stack,
103+
K_THREAD_STACK_SIZEOF(start_stack),
104+
lifo_put_get_thread_entry,
105+
(void *)(uintptr_t)num_iterations,
106+
(void *)(uintptr_t)options, NULL,
107+
priority - 1, options, K_FOREVER);
108+
109+
k_thread_access_grant(&start_thread, &pause_sem, &lifo);
110+
111+
k_thread_start(&start_thread);
112+
113+
if ((options & K_USER) == 0) {
114+
snprintf(description, sizeof(description),
115+
"LIFO put.immediate.%s",
116+
options & K_USER ? "user" : "kernel");
117+
118+
cycles = timestamp.cycles;
119+
cycles -= timestamp_overhead_adjustment(options, options);
120+
PRINT_STATS_AVG(description, (uint32_t)cycles,
121+
num_iterations, false, "");
122+
k_sem_give(&pause_sem);
123+
124+
snprintf(description, sizeof(description),
125+
"LIFO get.immediate.%s",
126+
options & K_USER ? "user" : "kernel");
127+
cycles = timestamp.cycles;
128+
cycles -= timestamp_overhead_adjustment(options, options);
129+
PRINT_STATS_AVG(description, (uint32_t)cycles,
130+
num_iterations, false, "");
131+
k_sem_give(&pause_sem);
132+
}
133+
134+
snprintf(description, sizeof(description),
135+
"LIFO put.alloc.immediate.%s",
136+
options & K_USER ? "user" : "kernel");
137+
138+
cycles = timestamp.cycles;
139+
PRINT_STATS_AVG(description, (uint32_t)cycles,
140+
num_iterations, false, "");
141+
k_sem_give(&pause_sem);
142+
143+
snprintf(description, sizeof(description),
144+
"LIFO get.free.immediate.%s",
145+
options & K_USER ? "user" : "kernel");
146+
cycles = timestamp.cycles;
147+
PRINT_STATS_AVG(description, (uint32_t)cycles,
148+
num_iterations, false, "");
149+
150+
k_thread_join(&start_thread, K_FOREVER);
151+
152+
timing_stop();
153+
154+
return 0;
155+
}
156+
157+
static void alt_thread_entry(void *p1, void *p2, void *p3)
158+
{
159+
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
160+
uint32_t options = (uint32_t)(uintptr_t)p2;
161+
timing_t start;
162+
timing_t mid;
163+
timing_t finish;
164+
uint64_t sum[4] = {0ULL, 0ULL, 0ULL, 0ULL};
165+
uintptr_t *data;
166+
uint32_t i;
167+
168+
if ((options & K_USER) == 0) {
169+
170+
/* Used with k_lifo_put() */
171+
172+
for (i = 0; i < num_iterations; i++) {
173+
174+
/* 1. Block waiting for data on LIFO */
175+
176+
start = timing_timestamp_get();
177+
178+
data = k_lifo_get(&lifo, K_FOREVER);
179+
180+
/* 3. Data obtained. */
181+
182+
finish = timing_timestamp_get();
183+
184+
mid = timestamp.sample;
185+
186+
sum[0] += timing_cycles_get(&start, &mid);
187+
sum[1] += timing_cycles_get(&mid, &finish);
188+
}
189+
}
190+
191+
/* Used with k_lifo_alloc_put() */
192+
193+
for (i = 0; i < num_iterations; i++) {
194+
195+
/* 4. Block waiting for data on LIFO */
196+
197+
start = timing_timestamp_get();
198+
199+
data = k_lifo_get(&lifo, K_FOREVER);
200+
201+
/* 6. Data obtained */
202+
203+
finish = timing_timestamp_get();
204+
205+
mid = timestamp.sample;
206+
207+
sum[2] += timing_cycles_get(&start, &mid);
208+
sum[3] += timing_cycles_get(&mid, &finish);
209+
}
210+
211+
if ((options & K_USER) == 0) {
212+
timestamp.cycles = sum[0];
213+
k_sem_take(&pause_sem, K_FOREVER);
214+
timestamp.cycles = sum[1];
215+
k_sem_take(&pause_sem, K_FOREVER);
216+
}
217+
218+
timestamp.cycles = sum[2];
219+
k_sem_take(&pause_sem, K_FOREVER);
220+
timestamp.cycles = sum[3];
221+
}
222+
223+
static void start_thread_entry(void *p1, void *p2, void *p3)
224+
{
225+
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
226+
uint32_t options = (uint32_t)(uintptr_t)p2;
227+
uint32_t i;
228+
229+
k_thread_start(&alt_thread);
230+
231+
if ((options & K_USER) == 0) {
232+
for (i = 0; i < num_iterations; i++) {
233+
234+
/* 2. Add data thereby waking alt thread */
235+
236+
timestamp.sample = timing_timestamp_get();
237+
238+
k_lifo_put(&lifo, lifo_data);
239+
240+
}
241+
}
242+
243+
for (i = 0; i < num_iterations; i++) {
244+
245+
/* 5. Add data thereby waking alt thread */
246+
247+
timestamp.sample = timing_timestamp_get();
248+
249+
k_lifo_alloc_put(&lifo, lifo_data);
250+
251+
}
252+
253+
k_thread_join(&alt_thread, K_FOREVER);
254+
}
255+
256+
int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
257+
uint32_t alt_options)
258+
{
259+
int priority;
260+
uint64_t cycles;
261+
char description[80];
262+
263+
priority = k_thread_priority_get(k_current_get());
264+
265+
timing_start();
266+
267+
k_thread_create(&start_thread, start_stack,
268+
K_THREAD_STACK_SIZEOF(start_stack),
269+
start_thread_entry,
270+
(void *)(uintptr_t)num_iterations,
271+
(void *)(uintptr_t)(start_options | alt_options), NULL,
272+
priority - 1, start_options, K_FOREVER);
273+
274+
k_thread_create(&alt_thread, alt_stack,
275+
K_THREAD_STACK_SIZEOF(alt_stack),
276+
alt_thread_entry,
277+
(void *)(uintptr_t)num_iterations,
278+
(void *)(uintptr_t)(start_options | alt_options), NULL,
279+
priority - 2, alt_options, K_FOREVER);
280+
281+
k_thread_access_grant(&start_thread, &alt_thread, &pause_sem, &lifo);
282+
k_thread_access_grant(&alt_thread, &pause_sem, &lifo);
283+
284+
k_thread_start(&start_thread);
285+
286+
if (((start_options | alt_options) & K_USER) == 0) {
287+
snprintf(description, sizeof(description),
288+
"LIFO get.blocking.(%s -> %s)",
289+
alt_options & K_USER ? "U" : "K",
290+
start_options & K_USER ? "U" : "K");
291+
292+
cycles = timestamp.cycles;
293+
PRINT_STATS_AVG(description, (uint32_t)cycles,
294+
num_iterations, false, "");
295+
k_sem_give(&pause_sem);
296+
297+
snprintf(description, sizeof(description),
298+
"LIFO put.wake+ctx.(%s -> %s)",
299+
start_options & K_USER ? "U" : "K",
300+
alt_options & K_USER ? "U" : "K");
301+
cycles = timestamp.cycles;
302+
PRINT_STATS_AVG(description, (uint32_t)cycles,
303+
num_iterations, false, "");
304+
k_sem_give(&pause_sem);
305+
}
306+
307+
snprintf(description, sizeof(description),
308+
"LIFO get.free.blocking.(%s -> %s)",
309+
alt_options & K_USER ? "U" : "K",
310+
start_options & K_USER ? "U" : "K");
311+
312+
cycles = timestamp.cycles;
313+
PRINT_STATS_AVG(description, (uint32_t)cycles,
314+
num_iterations, false, "");
315+
k_sem_give(&pause_sem);
316+
317+
snprintf(description, sizeof(description),
318+
"LIFO put.alloc.wake+ctx.(%s -> %s)",
319+
start_options & K_USER ? "U" : "K",
320+
alt_options & K_USER ? "U" : "K");
321+
cycles = timestamp.cycles;
322+
PRINT_STATS_AVG(description, (uint32_t)cycles,
323+
num_iterations, false, "");
324+
325+
k_thread_join(&start_thread, K_FOREVER);
326+
327+
timing_stop();
328+
329+
return 0;
330+
}

tests/benchmarks/latency_measure/src/main.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2012-2015 Wind River Systems, Inc.
3-
* Copyright (c) 2023 Intel Corporation.
3+
* Copyright (c) 2023,2024 Intel Corporation.
44
*
55
* SPDX-License-Identifier: Apache-2.0
66
*/
@@ -46,6 +46,9 @@ extern void sema_context_switch(uint32_t num_iterations,
4646
uint32_t start_options, uint32_t alt_options);
4747
extern int thread_ops(uint32_t num_iterations, uint32_t start_options,
4848
uint32_t alt_options);
49+
extern int lifo_ops(uint32_t num_iterations, uint32_t options);
50+
extern int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
51+
uint32_t alt_options);
4952
extern void heap_malloc_free(void);
5053

5154
static void test_thread(void *arg1, void *arg2, void *arg3)
@@ -89,6 +92,18 @@ static void test_thread(void *arg1, void *arg2, void *arg3)
8992
thread_ops(NUM_ITERATIONS, K_USER, 0);
9093
#endif
9194

95+
lifo_ops(NUM_ITERATIONS, 0);
96+
#ifdef CONFIG_USERSPACE
97+
lifo_ops(NUM_ITERATIONS, K_USER);
98+
#endif
99+
100+
lifo_blocking_ops(NUM_ITERATIONS, 0, 0);
101+
#ifdef CONFIG_USERSPACE
102+
lifo_blocking_ops(NUM_ITERATIONS, 0, K_USER);
103+
lifo_blocking_ops(NUM_ITERATIONS, K_USER, 0);
104+
lifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER);
105+
#endif
106+
92107
sema_test_signal(NUM_ITERATIONS, 0);
93108
#ifdef CONFIG_USERSPACE
94109
sema_test_signal(NUM_ITERATIONS, K_USER);

0 commit comments

Comments
 (0)