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