1 /*
2 * Copyright (c) 2019 Intel corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /* Disable syscall tracing for all calls from this compilation unit to avoid
8 * undefined symbols as the macros are not expanded recursively
9 */
10 #define DISABLE_SYSCALL_TRACING
11
12 #include <zephyr/init.h>
13 #include <string.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/util.h>
16 #include <zephyr/sys/atomic.h>
17 #include <tracing_core.h>
18 #include <tracing_buffer.h>
19 #include <tracing_backend.h>
20
21 #define TRACING_CMD_ENABLE "enable"
22 #define TRACING_CMD_DISABLE "disable"
23
24 #ifdef CONFIG_TRACING_BACKEND_UART
25 #define TRACING_BACKEND_NAME "tracing_backend_uart"
26 #elif defined CONFIG_TRACING_BACKEND_USB
27 #define TRACING_BACKEND_NAME "tracing_backend_usb"
28 #elif defined CONFIG_TRACING_BACKEND_POSIX
29 #define TRACING_BACKEND_NAME "tracing_backend_posix"
30 #elif defined CONFIG_TRACING_BACKEND_RAM
31 #define TRACING_BACKEND_NAME "tracing_backend_ram"
32 #elif defined CONFIG_TRACING_BACKEND_ADSP_MEMORY_WINDOW
33 #define TRACING_BACKEND_NAME "tracing_backend_adsp_memory_window"
34 #else
35 #define TRACING_BACKEND_NAME ""
36 #endif
37
38 enum tracing_state {
39 TRACING_DISABLE = 0,
40 TRACING_ENABLE
41 };
42
43 static atomic_t tracing_state;
44 static atomic_t tracing_packet_drop_num;
45 static struct tracing_backend *working_backend;
46
47 #ifdef CONFIG_TRACING_ASYNC
48 #define TRACING_THREAD_NAME "tracing_thread"
49
50 static k_tid_t tracing_thread_tid;
51 static struct k_thread tracing_thread;
52 static struct k_timer tracing_thread_timer;
53 static K_SEM_DEFINE(tracing_thread_sem, 0, 1);
54 static K_THREAD_STACK_DEFINE(tracing_thread_stack,
55 CONFIG_TRACING_THREAD_STACK_SIZE);
56
tracing_thread_func(void * dummy1,void * dummy2,void * dummy3)57 static void tracing_thread_func(void *dummy1, void *dummy2, void *dummy3)
58 {
59 uint8_t *transferring_buf;
60 uint32_t transferring_length, tracing_buffer_max_length;
61
62 tracing_thread_tid = k_current_get();
63
64 tracing_buffer_max_length = tracing_buffer_capacity_get();
65
66 while (true) {
67 if (tracing_buffer_is_empty()) {
68 k_sem_take(&tracing_thread_sem, K_FOREVER);
69 } else {
70 transferring_length =
71 tracing_buffer_get_claim(
72 &transferring_buf,
73 tracing_buffer_max_length);
74 tracing_buffer_handle(transferring_buf,
75 transferring_length);
76 tracing_buffer_get_finish(transferring_length);
77 }
78 }
79 }
80
tracing_thread_timer_expiry_fn(struct k_timer * timer)81 static void tracing_thread_timer_expiry_fn(struct k_timer *timer)
82 {
83 k_sem_give(&tracing_thread_sem);
84 }
85 #endif
86
tracing_set_state(enum tracing_state state)87 static void tracing_set_state(enum tracing_state state)
88 {
89 atomic_set(&tracing_state, state);
90 }
91
tracing_init(void)92 static int tracing_init(void)
93 {
94
95 tracing_buffer_init();
96
97 working_backend = tracing_backend_get(TRACING_BACKEND_NAME);
98 tracing_backend_init(working_backend);
99
100 atomic_set(&tracing_packet_drop_num, 0);
101
102 if (IS_ENABLED(CONFIG_TRACING_HANDLE_HOST_CMD)) {
103 tracing_set_state(TRACING_DISABLE);
104 } else {
105 tracing_set_state(TRACING_ENABLE);
106 }
107
108 #ifdef CONFIG_TRACING_ASYNC
109 k_timer_init(&tracing_thread_timer,
110 tracing_thread_timer_expiry_fn, NULL);
111
112 k_thread_create(&tracing_thread, tracing_thread_stack,
113 K_THREAD_STACK_SIZEOF(tracing_thread_stack),
114 tracing_thread_func, NULL, NULL, NULL,
115 K_LOWEST_APPLICATION_THREAD_PRIO, 0, K_NO_WAIT);
116 k_thread_name_set(&tracing_thread, TRACING_THREAD_NAME);
117 #endif
118
119 return 0;
120 }
121
122 SYS_INIT(tracing_init, APPLICATION, 0);
123
124 #ifdef CONFIG_TRACING_ASYNC
tracing_trigger_output(bool before_put_is_empty)125 void tracing_trigger_output(bool before_put_is_empty)
126 {
127 if (before_put_is_empty) {
128 k_timer_start(&tracing_thread_timer,
129 K_MSEC(CONFIG_TRACING_THREAD_WAIT_THRESHOLD),
130 K_NO_WAIT);
131 }
132 }
133
is_tracing_thread(void)134 bool is_tracing_thread(void)
135 {
136 return (!k_is_in_isr() && (k_current_get() == tracing_thread_tid));
137 }
138 #endif
139
is_tracing_enabled(void)140 bool is_tracing_enabled(void)
141 {
142 return atomic_get(&tracing_state) == TRACING_ENABLE;
143 }
144
tracing_cmd_handle(uint8_t * buf,uint32_t length)145 void tracing_cmd_handle(uint8_t *buf, uint32_t length)
146 {
147 if (strncmp(buf, TRACING_CMD_ENABLE, length) == 0) {
148 tracing_set_state(TRACING_ENABLE);
149 } else if (strncmp(buf, TRACING_CMD_DISABLE, length) == 0) {
150 tracing_set_state(TRACING_DISABLE);
151 }
152 }
153
tracing_buffer_handle(uint8_t * data,uint32_t length)154 void tracing_buffer_handle(uint8_t *data, uint32_t length)
155 {
156 tracing_backend_output(working_backend, data, length);
157 }
158
tracing_packet_drop_handle(void)159 void tracing_packet_drop_handle(void)
160 {
161 atomic_inc(&tracing_packet_drop_num);
162 }
163