Skip to content

Commit 7103b0c

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

File tree

2 files changed

+346
-0
lines changed

2 files changed

+346
-0
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 FIFO operations
9+
*
10+
* This file contains the tests that measures the times for the following
11+
* FIFO operations from both kernel threads and user threads:
12+
* 1. Immediately adding a data item to a FIFO
13+
* 2. Immediately removing a data item from a FIFO
14+
* 3. Immediately adding a data item to a FIFO with allocation
15+
* 4. Immediately removing a data item from a FIFO with allocation
16+
* 5. Blocking on removing a data item from a FIFO
17+
* 6. Waking (and context switching to) a thread blocked on a FIFO via
18+
* k_fifo_put().
19+
* 7. Waking (and context switching to) a thread blocked on a FIFO via
20+
* k_fifo_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_FIFO_DEFINE(fifo);
31+
32+
BENCH_BMEM uintptr_t fifo_data[5];
33+
34+
static void fifo_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_fifo_put(&fifo, fifo_data);
50+
51+
mid = timing_timestamp_get();
52+
53+
data = k_fifo_get(&fifo, 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_fifo_alloc_put(&fifo, fifo_data);
75+
76+
mid = timing_timestamp_get();
77+
78+
data = k_fifo_get(&fifo, 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 fifo_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+
fifo_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, &fifo);
110+
111+
k_thread_start(&start_thread);
112+
113+
if ((options & K_USER) == 0) {
114+
snprintf(description, sizeof(description),
115+
"FIFO 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+
"FIFO 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+
"FIFO 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+
"FIFO 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_fifo_put() */
171+
172+
for (i = 0; i < num_iterations; i++) {
173+
174+
/* 1. Block waiting for data on FIFO */
175+
176+
start = timing_timestamp_get();
177+
178+
data = k_fifo_get(&fifo, 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_fifo_alloc_put() */
192+
193+
for (i = 0; i < num_iterations; i++) {
194+
195+
/* 4. Block waiting for data on FIFO */
196+
197+
start = timing_timestamp_get();
198+
199+
data = k_fifo_get(&fifo, 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_fifo_put(&fifo, fifo_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_fifo_alloc_put(&fifo, fifo_data);
250+
251+
}
252+
253+
k_thread_join(&alt_thread, K_FOREVER);
254+
}
255+
256+
int fifo_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, &fifo);
282+
k_thread_access_grant(&alt_thread, &pause_sem, &fifo);
283+
284+
k_thread_start(&start_thread);
285+
286+
if (((start_options | alt_options) & K_USER) == 0) {
287+
snprintf(description, sizeof(description),
288+
"FIFO 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+
"FIFO 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+
"FIFO 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+
"FIFO 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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 fifo_ops(uint32_t num_iterations, uint32_t options);
50+
extern int fifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
51+
uint32_t alt_options);
4952
extern int lifo_ops(uint32_t num_iterations, uint32_t options);
5053
extern int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
5154
uint32_t alt_options);
@@ -92,6 +95,19 @@ static void test_thread(void *arg1, void *arg2, void *arg3)
9295
thread_ops(NUM_ITERATIONS, K_USER, 0);
9396
#endif
9497

98+
fifo_ops(NUM_ITERATIONS, 0);
99+
#ifdef CONFIG_USERSPACE
100+
fifo_ops(NUM_ITERATIONS, K_USER);
101+
#endif
102+
103+
fifo_blocking_ops(NUM_ITERATIONS, 0, 0);
104+
#ifdef CONFIG_USERSPACE
105+
fifo_blocking_ops(NUM_ITERATIONS, 0, K_USER);
106+
fifo_blocking_ops(NUM_ITERATIONS, K_USER, 0);
107+
fifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER);
108+
#endif
109+
110+
95111
lifo_ops(NUM_ITERATIONS, 0);
96112
#ifdef CONFIG_USERSPACE
97113
lifo_ops(NUM_ITERATIONS, K_USER);

0 commit comments

Comments
 (0)