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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 189 rt_inline void rt_slist_init(rt_slist_t *l) 190 { 191 l->next = RT_NULL; 192 } 193 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 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 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 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 237 rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l) 238 { 239 return l->next; 240 } 241 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 249 rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n) 250 { 251 return n->next; 252 } 253 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