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 enum tracing_state {
25 TRACING_DISABLE = 0,
26 TRACING_ENABLE
27 };
28
29 static atomic_t tracing_state;
30 static atomic_t tracing_packet_drop_num;
31 static struct tracing_backend *working_backend;
32
33 #ifdef CONFIG_TRACING_ASYNC
34 #define TRACING_THREAD_NAME "tracing_thread"
35
36 static k_tid_t tracing_thread_tid;
37 static struct k_thread tracing_thread;
38 static struct k_timer tracing_thread_timer;
39 static K_SEM_DEFINE(tracing_thread_sem, 0, 1);
40 static K_THREAD_STACK_DEFINE(tracing_thread_stack,
41 CONFIG_TRACING_THREAD_STACK_SIZE);
42
tracing_thread_func(void * dummy1,void * dummy2,void * dummy3)43 static void tracing_thread_func(void *dummy1, void *dummy2, void *dummy3)
44 {
45 uint8_t *transferring_buf;
46 uint32_t transferring_length, tracing_buffer_max_length;
47
48 tracing_thread_tid = k_current_get();
49
50 tracing_buffer_max_length = tracing_buffer_capacity_get();
51
52 while (true) {
53 if (tracing_buffer_is_empty()) {
54 k_sem_take(&tracing_thread_sem, K_FOREVER);
55 } else {
56 transferring_length =
57 tracing_buffer_get_claim(
58 &transferring_buf,
59 tracing_buffer_max_length);
60 tracing_buffer_handle(transferring_buf,
61 transferring_length);
62 tracing_buffer_get_finish(transferring_length);
63 }
64 }
65 }
66
tracing_thread_timer_expiry_fn(struct k_timer * timer)67 static void tracing_thread_timer_expiry_fn(struct k_timer *timer)
68 {
69 k_sem_give(&tracing_thread_sem);
70 }
71 #endif
72
tracing_set_state(enum tracing_state state)73 static void tracing_set_state(enum tracing_state state)
74 {
75 atomic_set(&tracing_state, state);
76 }
77
tracing_init(void)78 static int tracing_init(void)
79 {
80
81 tracing_buffer_init();
82
83 working_backend = tracing_backend_get(CONFIG_TRACING_BACKEND_NAME);
84 tracing_backend_init(working_backend);
85
86 atomic_set(&tracing_packet_drop_num, 0);
87
88 if (IS_ENABLED(CONFIG_TRACING_HANDLE_HOST_CMD)) {
89 tracing_set_state(TRACING_DISABLE);
90 } else {
91 tracing_set_state(TRACING_ENABLE);
92 }
93
94 #ifdef CONFIG_TRACING_ASYNC
95 k_timer_init(&tracing_thread_timer,
96 tracing_thread_timer_expiry_fn, NULL);
97
98 k_thread_create(&tracing_thread, tracing_thread_stack,
99 K_THREAD_STACK_SIZEOF(tracing_thread_stack),
100 tracing_thread_func, NULL, NULL, NULL,
101 K_LOWEST_APPLICATION_THREAD_PRIO, 0, K_NO_WAIT);
102 k_thread_name_set(&tracing_thread, TRACING_THREAD_NAME);
103 #endif
104
105 return 0;
106 }
107
108 SYS_INIT(tracing_init, APPLICATION, 0);
109
110 #ifdef CONFIG_TRACING_ASYNC
tracing_trigger_output(bool before_put_is_empty)111 void tracing_trigger_output(bool before_put_is_empty)
112 {
113 if (before_put_is_empty) {
114 k_timer_start(&tracing_thread_timer,
115 K_MSEC(CONFIG_TRACING_THREAD_WAIT_THRESHOLD),
116 K_NO_WAIT);
117 }
118 }
119
is_tracing_thread(void)120 bool is_tracing_thread(void)
121 {
122 return (!k_is_in_isr() && (k_current_get() == tracing_thread_tid));
123 }
124 #endif
125
is_tracing_enabled(void)126 bool is_tracing_enabled(void)
127 {
128 return atomic_get(&tracing_state) == TRACING_ENABLE;
129 }
130
tracing_cmd_handle(uint8_t * buf,uint32_t length)131 void tracing_cmd_handle(uint8_t *buf, uint32_t length)
132 {
133 if (strncmp(buf, TRACING_CMD_ENABLE, length) == 0) {
134 tracing_set_state(TRACING_ENABLE);
135 } else if (strncmp(buf, TRACING_CMD_DISABLE, length) == 0) {
136 tracing_set_state(TRACING_DISABLE);
137 }
138 }
139
tracing_buffer_handle(uint8_t * data,uint32_t length)140 void tracing_buffer_handle(uint8_t *data, uint32_t length)
141 {
142 tracing_backend_output(working_backend, data, length);
143 }
144
tracing_packet_drop_handle(void)145 void tracing_packet_drop_handle(void)
146 {
147 atomic_inc(&tracing_packet_drop_num);
148 }
149