GCC Code Coverage Report


Directory: kernel/
File: kernel/include/puppy/util.h
Date: 2024-01-01 16:15:14
Exec Total Coverage
Lines: 26 26 100.0%
Functions: 6 6 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2022-2023, The Puppy RTOS Authors
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #ifndef PUPPY_INC_UTIL_H__
7 #define PUPPY_INC_UTIL_H__
8
9 int p_hw_borad_init(void);
10 int p_hw_cons_getc(void);
11 int p_hw_cons_output(const char *str, int len);
12 int printk(const char *fmt, ...);
13
14 #define P_ROM_SECTION "puppy_rom_sym."
15 #define P_RAM_SECTION "puppy_ram_sym."
16
17 #define P_SECTION_DATA(x) p_section(x ".1")
18 #define P_SECTION_START_DEFINE(x, name) p_used static p_base_t name p_section(x ".0")
19 #define P_SECTION_END_DEFINE(x, name) p_used static p_base_t name p_section(x ".2")
20 #define P_SECTION_START_ADDR(name) (&name + 1)
21 #define P_SECTION_END_ADDR(name) (&name)
22
23 #define P_TC_PASS() printk("Test Passed! at %s:%d\r\n", __FUNCTION__, __LINE__);
24 #define P_TC_FAIL() printk("Test Failed! at %s:%d\r\n", __FUNCTION__, __LINE__);
25 #define P_TC_LOG(...) do {printk(__VA_ARGS__); printk("\r\n");} while (0);
26
27 struct p_ex_fn
28 {
29 const char *name;
30 void (*func)(void);
31 };
32
33 #define P_TC_SECTION P_ROM_SECTION "P_TC_LIST"
34 #define P_TC_FUNC(fn, name) \
35 p_used const static struct p_ex_fn _p_tc_##fn \
36 P_SECTION_DATA(P_TC_SECTION) = { #name, fn}
37
38 #define P_INIT_SECTION P_ROM_SECTION "P_INIT_LIST"
39 #define P_INIT_FUNC(fn) \
40 p_used const char _init_##fn##_name[] = #fn; \
41 p_used const static struct p_ex_fn _init_##fn \
42 P_SECTION_DATA(P_INIT_SECTION) = { _init_##fn##_name, fn}
43
44 /**
45 * p_container_of - return the start address of struct type, while ptr is the
46 * member of struct type.
47 */
48 #define p_container_of(ptr, type, member) \
49 ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
50
51 /**
52 * @brief list
53 *
54 */
55 struct _list_node {
56 union {
57 struct _list_node *head; /* ptr to head of list (p_list_t) */
58 struct _list_node *next; /* ptr to next node (p_node_t) */
59 };
60 union {
61 struct _list_node *tail; /* ptr to tail of list (p_list_t) */
62 struct _list_node *prev; /* ptr to previous node (p_node_t) */
63 };
64 };
65 typedef struct _list_node p_list_t;
66 typedef struct _list_node p_node_t;
67
68
69
70 /**
71 * @brief get the struct for this entry
72 * @param node the entry point
73 * @param type the type of structure
74 * @param member the name of list in structure
75 */
76 #define p_list_entry(node, type, member) \
77 p_container_of(node, type, member)
78
79 /**
80 * @brief Provide the primitive to iterate on a list
81 * Note: the loop is unsafe and thus node should not be removed
82 * @param list A pointer on a p_list_t to iterate on.
83 * @param node A p_node_t pointer to peek each node of the list
84 */
85 #define p_list_for_each_node(list, node) \
86 for (node = (list)->head; node != (list); node = node->next)
87
88 /**
89 * @brief Provide the primitive to safely iterate on a list
90 * Note: node can be removed, it will not break the loop.
91 * @param list A pointer on a p_list_t to iterate on.
92 * @param node A p_node_t pointer to peek each node of the list
93 * @param node_s A p_node_t pointer for the loop to run safely
94 */
95 #define p_list_for_each_node_safe(list, node, node_s) \
96 for (node = (list)->head, node_s = node->next; node != (list); \
97 node = node_s, node_s = node->next)
98
99 #define P_LIST_STATIC_INIT(list_ptr) { {(list_ptr)}, {(list_ptr)} }
100
101 35 static inline void p_list_init(p_list_t *list)
102 {
103 35 list->head = list->tail = list;
104 35 }
105
106 5343 static inline bool p_list_is_empty(p_list_t *list)
107 {
108 5343 return list->head == list;
109 }
110
111 66 static inline bool p_node_is_linked(p_node_t *node)
112 {
113 66 return node->next != NULL;
114 }
115
116 /**
117 * @brief add node to tail of list
118 *
119 * This and other p_list_*() functions are not thread safe.
120 *
121 * @param list the doubly-linked list to operate on
122 * @param node the element to append
123 */
124
125 543 static inline void p_list_append(p_list_t *list, p_node_t *node)
126 {
127 543 p_node_t *const tail = list->tail;
128
129 543 node->next = list;
130 543 node->prev = tail;
131
132 543 tail->next = node;
133 543 list->tail = node;
134 543 }
135
136 /**
137 * @brief add node to head of list
138 *
139 * This and other p_list_*() functions are not thread safe.
140 *
141 * @param list the doubly-linked list to operate on
142 * @param node the element to append
143 */
144
145 static inline void p_list_prepend(p_list_t *list, p_node_t *node)
146 {
147 p_node_t *const head = list->head;
148
149 node->next = head;
150 node->prev = list;
151
152 head->prev = node;
153 list->head = node;
154 }
155
156 /**
157 * @brief Insert a node into a list
158 *
159 * Insert a node before a specified node in a dlist.
160 *
161 * @param successor the position before which "node" will be inserted
162 * @param node the element to insert
163 */
164 19 static inline void p_list_insert(p_node_t *successor, p_node_t *node)
165 {
166 19 p_node_t *const prev = successor->prev;
167
168 19 node->prev = prev;
169 19 node->next = successor;
170 19 prev->next = node;
171 19 successor->prev = node;
172 19 }
173
174 /**
175 * @brief remove node from list.
176 * @param node the node to remove from the list.
177 */
178 552 static inline void p_list_remove(p_node_t *node)
179 {
180 552 node->next->prev = node->prev;
181 552 node->prev->next = node->next;
182
183 552 node->prev = node->next = NULL;
184 552 }
185
186 typedef struct {
187 uint8_t *buffer;
188 size_t size;
189 atomic_size_t head;
190 atomic_size_t tail;
191 } p_rb_t;
192
193 static inline bool p_rb_init(p_rb_t *rb, uint8_t *buffer, size_t size)
194 {
195 if (rb == NULL || buffer == NULL || size == 0)
196 {
197 return false;
198 }
199 rb->buffer = buffer;
200 rb->size = size;
201 atomic_init(&rb->head, 0);
202 atomic_init(&rb->tail, 0);
203 return true;
204 }
205
206 static inline bool p_rb_write(p_rb_t *rb, const uint8_t *data, size_t length)
207 {
208 if (rb == NULL || data == NULL || length == 0) {
209 return false;
210 }
211
212 size_t head = atomic_load_explicit(&rb->head, memory_order_relaxed);
213 size_t tail = atomic_load_explicit(&rb->tail, memory_order_acquire);
214
215 if (tail + rb->size - head < length) {
216 return false;
217 }
218
219 for (size_t i = 0; i < length; ++i) {
220 rb->buffer[head % rb->size] = data[i];
221 ++head;
222 }
223
224 atomic_store_explicit(&rb->head, head, memory_order_release);
225
226 return true;
227 }
228
229 static inline bool p_rb_read(p_rb_t *rb, uint8_t *data, size_t length)
230 {
231 if (rb == NULL || data == NULL || length == 0) {
232 return false;
233 }
234
235 size_t head = atomic_load_explicit(&rb->head, memory_order_acquire);
236 size_t tail = atomic_load_explicit(&rb->tail, memory_order_relaxed);
237
238 if (head - tail < length) {
239 return false;
240 }
241
242 for (size_t i = 0; i < length; ++i) {
243 data[i] = rb->buffer[tail % rb->size];
244 ++tail;
245 }
246
247 atomic_store_explicit(&rb->tail, tail, memory_order_release);
248
249 return true;
250 }
251
252 #endif
253