1 /*
2  * Copyright (c) 2019 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Test log immediate
10  *
11  */
12 
13 
14 #include <zephyr/tc_util.h>
15 #include <stdbool.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/ztest.h>
18 #include <zephyr/logging/log_backend.h>
19 #include <zephyr/logging/log_ctrl.h>
20 #include <zephyr/logging/log.h>
21 
22 #define LOG_MODULE_NAME test
23 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
24 
25 #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
26 
27 #define NUM_THREADS 5
28 
29 K_THREAD_STACK_ARRAY_DEFINE(stacks, NUM_THREADS, STACK_SIZE);
30 static struct k_thread threads[NUM_THREADS];
31 static k_tid_t tids[NUM_THREADS];
32 
33 
34 /* Thread entry point, used for multiple threads. Thread is logging some data
35  * (data length varies for each thread) and sleeps. Threads have different
36  * priorities so on wakeup other thread will be preempted, interrupting logging.
37  */
thread_func(void * p1,void * p2,void * p3)38 static void thread_func(void *p1, void *p2, void *p3)
39 {
40 	intptr_t id = (intptr_t)p1;
41 	int buf_len = 8*id + 8;
42 	uint8_t *buf = alloca(buf_len);
43 
44 	while (1) {
45 		LOG_INF("test string printed %d %d %p", 1, 2, k_current_get());
46 		LOG_HEXDUMP_INF(buf, buf_len, "data:");
47 		k_msleep(20+id);
48 	}
49 }
50 
51 /*
52  * Test create number of threads with different priorities. Each thread logs
53  * data and sleeps. This creates environment where multiple threads are
54  * preempted during logging (in immediate mode). Test checks that system does
55  * not hit any assert or other fault during frequent preemptions.
56  */
ZTEST(log_immediate,test_log_immediate_preemption)57 ZTEST(log_immediate, test_log_immediate_preemption)
58 {
59 	if (!IS_ENABLED(CONFIG_LOG_IMMEDIATE_CLEAN_OUTPUT)) {
60 		LOG_INF("CONFIG_LOG_IMMEDIATE_CLEAN_OUTPUT not enabled."
61 			" Text output will be garbled.");
62 	}
63 	for (intptr_t i = 0; i < NUM_THREADS; i++) {
64 		tids[i] = k_thread_create(&threads[i], stacks[i], STACK_SIZE,
65 				thread_func, (void *)i, NULL, NULL,
66 				k_thread_priority_get(k_current_get()) + i,
67 				0, K_MSEC(10));
68 	}
69 	k_msleep(3000);
70 
71 	for (int i = 0; i < NUM_THREADS; i++) {
72 		k_thread_abort(tids[i]);
73 	}
74 	zassert_true(true, "");
75 }
76 
77 ZTEST_SUITE(log_immediate, NULL, NULL, NULL, NULL, NULL);
78