rtservice.h 9.0 KB

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