Skip to content

Commit 86c5cf1

Browse files
nroyer-baylibrenashif
authored andcommitted
samples: userspace: syscall_perf
The goal of this sample application is to measure the performance loss when a user thread has to go through a system call compared to a supervisor thread that calls the function directly. Signed-off-by: Nicolas Royer <[email protected]>
1 parent c9a3fca commit 86c5cf1

File tree

9 files changed

+240
-0
lines changed

9 files changed

+240
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.13.1)
4+
5+
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
6+
project(syscall_perf)
7+
8+
set_property(
9+
SOURCE src/test_user.c
10+
PROPERTY COMPILE_DEFINITIONS
11+
__ZEPHYR_USER__
12+
)
13+
14+
set_property(
15+
SOURCE src/test_supervisor.c
16+
PROPERTY COMPILE_DEFINITIONS
17+
__ZEPHYR_SUPERVISOR__
18+
)
19+
20+
target_sources(app PRIVATE src/main.c src/test_user.c src/test_supervisor.c)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
.. _syscall_perf:
2+
3+
Syscall performances
4+
====================
5+
6+
The goal of this sample application is to measure the performance loss when a
7+
user thread has to go through a system call compared to a supervisor thread that
8+
calls the function directly.
9+
10+
11+
Overview
12+
********
13+
14+
This application creates a supervisor and a user thread.
15+
Then both threads call k_current_get() which returns a reference to the
16+
current thread. The user thread has to go through a system call.
17+
18+
Both threads are showing the number of core clock cycles and the number of
19+
instructions executed while calling k_current_get().
20+
21+
22+
Sample Output
23+
*************
24+
25+
.. code-block:: console
26+
27+
User thread: 18012 cycles 748 instructions
28+
Supervisor thread: 7 cycles 4 instructions
29+
User thread: 20136 cycles 748 instructions
30+
Supervisor thread: 7 cycles 4 instructions
31+
User thread: 18014 cycles 748 instructions
32+
Supervisor thread: 7 cycles 4 instructions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONFIG_USERSPACE=y
2+
CONFIG_APPLICATION_DEFINED_SYSCALL=y
3+
CONFIG_ASSERT=y
4+
CONFIG_LOG=y
5+
CONFIG_LOG_MINIMAL=y
6+
CONFIG_MAIN_STACK_SIZE=2560
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
sample:
2+
description: syscall performances sample
3+
name: syscall performances
4+
common:
5+
tags: userspace
6+
harness: console
7+
harness_config:
8+
type: one_line
9+
regex:
10+
- "User thread"
11+
tests:
12+
sample.syscall_performances:
13+
filter: CONFIG_ARCH_HAS_USERSPACE
14+
platform_allow: riscv32
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2020 BayLibre, SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr.h>
8+
#include <stdio.h>
9+
10+
#include "main.h"
11+
#include "thread_def.h"
12+
13+
void main(void)
14+
{
15+
printf("Main Thread started; %s\n", CONFIG_BOARD);
16+
17+
k_thread_create(&supervisor_thread, supervisor_stack, THREAD_STACKSIZE,
18+
supervisor_thread_function, NULL, NULL, NULL,
19+
-1, K_INHERIT_PERMS, K_NO_WAIT);
20+
21+
k_sleep(K_MSEC(1000));
22+
23+
k_thread_create(&user_thread, user_stack, THREAD_STACKSIZE,
24+
user_thread_function, NULL, NULL, NULL,
25+
-1, K_USER | K_INHERIT_PERMS, K_NO_WAIT);
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2020 BayLibre, SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef MAIN_H
8+
#define MAIN_H
9+
10+
#include <kernel.h>
11+
12+
#define csr_read(csr) \
13+
({ \
14+
register unsigned long __v; \
15+
__asm__ volatile ("csrr %0, " #csr \
16+
: "=r" (__v)); \
17+
__v; \
18+
})
19+
20+
#endif /* MAIN_H */
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2020 BayLibre, SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr.h>
8+
#include <stdio.h>
9+
10+
#include "main.h"
11+
12+
/*
13+
* 0xB00 is CSR mcycle
14+
* 0xB02 is CSR minstret
15+
*/
16+
void supervisor_thread_function(void *p1, void *p2, void *p3)
17+
{
18+
register unsigned long cycle_before, cycle_count;
19+
register unsigned long inst_before, inst_count;
20+
21+
printf("Supervisor thread started\n");
22+
23+
while (1) {
24+
k_sleep(K_MSEC(2000));
25+
26+
inst_before = csr_read(0xB02);
27+
cycle_before = csr_read(0xB00);
28+
k_current_get();
29+
cycle_count = csr_read(0xB00);
30+
inst_count = csr_read(0xB02);
31+
32+
if (cycle_count > cycle_before) {
33+
cycle_count -= cycle_before;
34+
} else {
35+
cycle_count += 0xFFFFFFFF - cycle_before;
36+
}
37+
38+
if (inst_count > inst_before) {
39+
inst_count -= inst_before;
40+
} else {
41+
inst_count += 0xFFFFFFFF - inst_before;
42+
}
43+
44+
/* Remove CSR accesses to be more accurate */
45+
inst_count -= 3;
46+
47+
printf("Supervisor thread:\t%8lu cycles\t%8lu instructions\n",
48+
cycle_count, inst_count);
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2020 BayLibre, SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr.h>
8+
#include <stdio.h>
9+
10+
#include "main.h"
11+
12+
/*
13+
* 0xC00 is CSR cycle
14+
* 0xC02 is CSR instret
15+
*/
16+
void user_thread_function(void *p1, void *p2, void *p3)
17+
{
18+
register unsigned long cycle_before, cycle_count;
19+
register unsigned long inst_before, inst_count;
20+
21+
printf("User thread started\n");
22+
23+
while (1) {
24+
k_sleep(K_MSEC(2000));
25+
26+
inst_before = csr_read(0xC02);
27+
cycle_before = csr_read(0xC00);
28+
k_current_get();
29+
cycle_count = csr_read(0xC00);
30+
inst_count = csr_read(0xC02);
31+
32+
if (cycle_count > cycle_before) {
33+
cycle_count -= cycle_before;
34+
} else {
35+
cycle_count += 0xFFFFFFFF - cycle_before;
36+
}
37+
38+
if (inst_count > inst_before) {
39+
inst_count -= inst_before;
40+
} else {
41+
inst_count += 0xFFFFFFFF - inst_before;
42+
}
43+
44+
/* Remove CSR accesses to be more accurate */
45+
inst_count -= 3;
46+
47+
printf("User thread:\t\t%8lu cycles\t%8lu instructions\n",
48+
cycle_count, inst_count);
49+
}
50+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2020 BayLibre, SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef THREAD_DEF_H
8+
#define THREAD_DEF_H
9+
10+
#include <kernel.h>
11+
12+
#define THREAD_STACKSIZE 2048
13+
14+
struct k_thread user_thread;
15+
K_THREAD_STACK_DEFINE(user_stack, THREAD_STACKSIZE);
16+
void supervisor_thread_function(void *p1, void *p2, void *p3);
17+
18+
struct k_thread supervisor_thread;
19+
K_THREAD_STACK_DEFINE(supervisor_stack, THREAD_STACKSIZE);
20+
void user_thread_function(void *p1, void *p2, void *p3);
21+
22+
#endif /* THREAD_DEF_H */

0 commit comments

Comments
 (0)