1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2006-03-16     Bernard      the first version
9  * 2006-09-07     Bernard      move the kservice APIs to rtthread.h
10  * 2007-06-27     Bernard      fix the rt_list_remove bug
11  * 2012-03-22     Bernard      rename kservice.h to rtservice.h
12  * 2017-11-15     JasonJia     Modify rt_slist_foreach to rt_slist_for_each_entry.
13  *                             Make code cleanup.
14  * 2024-01-03     Shell        add rt_slist_pop()
15  */
16 
17 #ifndef __RT_SERVICE_H__
18 #define __RT_SERVICE_H__
19 
20 #include <rtdef.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /**
27  * @addtogroup group_kernel_service
28  */
29 
30 /**@{*/
31 
32 /**
33  * rt_container_of - return the start address of struct type, while ptr is the
34  * member of struct type.
35  */
36 #define rt_container_of(ptr, type, member) \
37     ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
38 
39 
40 /**
41  * @brief initialize a list object
42  */
43 #define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }
44 
45 /**
46  * @brief initialize a list
47  *
48  * @param l list to be initialized
49  */
rt_list_init(rt_list_t * l)50 rt_inline void rt_list_init(rt_list_t *l)
51 {
52     l->next = l->prev = l;
53 }
54 
55 /**
56  * @brief insert a node after a list
57  *
58  * @param l list to insert it
59  * @param n new node to be inserted
60  */
rt_list_insert_after(rt_list_t * l,rt_list_t * n)61 rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
62 {
63     l->next->prev = n;
64     n->next = l->next;
65 
66     l->next = n;
67     n->prev = l;
68 }
69 
70 /**
71  * @brief insert a node before a list
72  *
73  * @param n new node to be inserted
74  * @param l list to insert it
75  */
rt_list_insert_before(rt_list_t * l,rt_list_t * n)76 rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
77 {
78     l->prev->next = n;
79     n->prev = l->prev;
80 
81     l->prev = n;
82     n->next = l;
83 }
84 
85 /**
86  * @brief remove node from list.
87  * @param n the node to remove from the list.
88  */
rt_list_remove(rt_list_t * n)89 rt_inline void rt_list_remove(rt_list_t *n)
90 {
91     n->next->prev = n->prev;
92     n->prev->next = n->next;
93 
94     n->next = n->prev = n;
95 }
96 
97 /**
98  * @brief tests whether a list is empty
99  * @param l the list to test.
100  */
rt_list_isempty(const rt_list_t * l)101 rt_inline int rt_list_isempty(const rt_list_t *l)
102 {
103     return l->next == l;
104 }
105 
106 /**
107  * @brief get the list length
108  * @param l the list to get.
109  */
rt_list_len(const rt_list_t * l)110 rt_inline unsigned int rt_list_len(const rt_list_t *l)
111 {
112     unsigned int len = 0;
113     const rt_list_t *p = l;
114     while (p->next != l)
115     {
116         p = p->next;
117         len ++;
118     }
119 
120     return len;
121 }
122 
123 /**
124  * @brief get the struct for this entry
125  * @param node the entry point
126  * @param type the type of structure
127  * @param member the name of list in structure
128  */
129 #define rt_list_entry(node, type, member) \
130     rt_container_of(node, type, member)
131 
132 /**
133  * rt_list_for_each - iterate over a list
134  * @param pos the rt_list_t * to use as a loop cursor.
135  * @param head the head for your list.
136  */
137 #define rt_list_for_each(pos, head) \
138     for (pos = (head)->next; pos != (head); pos = pos->next)
139 
140 /**
141  * rt_list_for_each_safe - iterate over a list safe against removal of list entry
142  * @param pos the rt_list_t * to use as a loop cursor.
143  * @param n another rt_list_t * to use as temporary storage
144  * @param head the head for your list.
145  */
146 #define rt_list_for_each_safe(pos, n, head) \
147     for (pos = (head)->next, n = pos->next; pos != (head); \
148         pos = n, n = pos->next)
149 
150 /**
151  * rt_list_for_each_entry  -   iterate over list of given type
152  * @param pos the type * to use as a loop cursor.
153  * @param head the head for your list.
154  * @param member the name of the list_struct within the struct.
155  */
156 #define rt_list_for_each_entry(pos, head, member) \
157     for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member); \
158          &pos->member != (head); \
159          pos = rt_list_entry(pos->member.next, rt_typeof(*pos), member))
160 
161 /**
162  * rt_list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
163  * @param pos the type * to use as a loop cursor.
164  * @param n another type * to use as temporary storage
165  * @param head the head for your list.
166  * @param member the name of the list_struct within the struct.
167  */
168 #define rt_list_for_each_entry_safe(pos, n, head, member) \
169     for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member), \
170          n = rt_list_entry(pos->member.next, rt_typeof(*pos), member); \
171          &pos->member != (head); \
172          pos = n, n = rt_list_entry(n->member.next, rt_typeof(*n), member))
173 
174 /**
175  * rt_list_first_entry - get the first element from a list
176  * @param ptr the list head to take the element from.
177  * @param type the type of the struct this is embedded in.
178  * @param member the name of the list_struct within the struct.
179  *
180  * Note, that list is expected to be not empty.
181  */
182 #define rt_list_first_entry(ptr, type, member) \
183     rt_list_entry((ptr)->next, type, member)
184 
185 #define RT_SLIST_OBJECT_INIT(object) { RT_NULL }
186 
187 /**
188  * @brief initialize a single list
189  *
190  * @param l the single list to be initialized
191  */
rt_slist_init(rt_slist_t * l)192 rt_inline void rt_slist_init(rt_slist_t *l)
193 {
194     l->next = RT_NULL;
195 }
196 
rt_slist_append(rt_slist_t * l,rt_slist_t * n)197 rt_inline void rt_slist_append(rt_slist_t *l, rt_slist_t *n)
198 {
199     struct rt_slist_node *node;
200 
201     node = l;
202     while (node->next) node = node->next;
203 
204     /* append the node to the tail */
205     node->next = n;
206     n->next = RT_NULL;
207 }
208 
rt_slist_insert(rt_slist_t * l,rt_slist_t * n)209 rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n)
210 {
211     n->next = l->next;
212     l->next = n;
213 }
214 
rt_slist_len(const rt_slist_t * l)215 rt_inline unsigned int rt_slist_len(const rt_slist_t *l)
216 {
217     unsigned int len = 0;
218     const rt_slist_t *list = l->next;
219     while (list != RT_NULL)
220     {
221         list = list->next;
222         len ++;
223     }
224 
225     return len;
226 }
227 
rt_slist_pop(rt_slist_t * l)228 rt_inline rt_slist_t *rt_slist_pop(rt_slist_t *l)
229 {
230     struct rt_slist_node *node = l;
231 
232     /* remove node */
233     node = node->next;
234     if (node != (rt_slist_t *)0)
235     {
236         ((struct rt_slist_node *)l)->next = node->next;
237         node->next = RT_NULL;
238     }
239 
240     return node;
241 }
242 
rt_slist_remove(rt_slist_t * l,rt_slist_t * n)243 rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n)
244 {
245     /* remove slist head */
246     struct rt_slist_node *node = l;
247     while (node->next && node->next != n) node = node->next;
248 
249     /* remove node */
250     if (node->next != (rt_slist_t *)0)
251     {
252         node->next = node->next->next;
253         n->next = RT_NULL;
254     }
255 
256     return l;
257 }
258 
rt_slist_first(rt_slist_t * l)259 rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l)
260 {
261     return l->next;
262 }
263 
rt_slist_tail(rt_slist_t * l)264 rt_inline rt_slist_t *rt_slist_tail(rt_slist_t *l)
265 {
266     while (l->next) l = l->next;
267 
268     return l;
269 }
270 
rt_slist_next(rt_slist_t * n)271 rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n)
272 {
273     return n->next;
274 }
275 
rt_slist_isempty(rt_slist_t * l)276 rt_inline int rt_slist_isempty(rt_slist_t *l)
277 {
278     return l->next == RT_NULL;
279 }
280 
281 /**
282  * @brief get the struct for this single list node
283  * @param node the entry point
284  * @param type the type of structure
285  * @param member the name of list in structure
286  */
287 #define rt_slist_entry(node, type, member) \
288     rt_container_of(node, type, member)
289 
290 /**
291  * rt_slist_for_each - iterate over a single list
292  * @param pos the rt_slist_t * to use as a loop cursor.
293  * @param head the head for your single list.
294  */
295 #define rt_slist_for_each(pos, head) \
296     for (pos = (head)->next; pos != RT_NULL; pos = pos->next)
297 
298 /**
299  * rt_slist_for_each_entry  -   iterate over single list of given type
300  * @param pos the type * to use as a loop cursor.
301  * @param head the head for your single list.
302  * @param member the name of the list_struct within the struct.
303  */
304 #define rt_slist_for_each_entry(pos, head, member) \
305     for (pos = ((head)->next == (RT_NULL) ? (RT_NULL) : rt_slist_entry((head)->next, rt_typeof(*pos), member)); \
306          pos != (RT_NULL) && &pos->member != (RT_NULL); \
307          pos = (pos->member.next == (RT_NULL) ? (RT_NULL) : rt_slist_entry(pos->member.next, rt_typeof(*pos), member)))
308 
309 /**
310  * rt_slist_first_entry - get the first element from a slist
311  * @param ptr the slist head to take the element from.
312  * @param type the type of the struct this is embedded in.
313  * @param member the name of the slist_struct within the struct.
314  *
315  * Note, that slist is expected to be not empty.
316  */
317 #define rt_slist_first_entry(ptr, type, member) \
318     rt_slist_entry((ptr)->next, type, member)
319 
320 /**
321  * rt_slist_tail_entry - get the tail element from a slist
322  * @param ptr the slist head to take the element from.
323  * @param type the type of the struct this is embedded in.
324  * @param member the name of the slist_struct within the struct.
325  *
326  * Note, that slist is expected to be not empty.
327  */
328 #define rt_slist_tail_entry(ptr, type, member) \
329     rt_slist_entry(rt_slist_tail(ptr), type, member)
330 
331 /**@}*/
332 
333 #ifdef __cplusplus
334 }
335 #endif
336 
337 #endif
338