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