/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2006-03-16 Bernard the first version * 2006-09-07 Bernard move the kservice APIs to rtthread.h * 2007-06-27 Bernard fix the rt_list_remove bug * 2012-03-22 Bernard rename kservice.h to rtservice.h * 2017-11-15 JasonJia Modify rt_slist_foreach to rt_slist_for_each_entry. * Make code cleanup. * 2024-01-03 Shell add rt_slist_pop() */ #ifndef __RT_SERVICE_H__ #define __RT_SERVICE_H__ #include #ifdef __cplusplus extern "C" { #endif /** * @addtogroup KernelService */ /**@{*/ /** * rt_container_of - return the start address of struct type, while ptr is the * member of struct type. */ #define rt_container_of(ptr, type, member) \ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) /** * @brief initialize a list object */ #define RT_LIST_OBJECT_INIT(object) { &(object), &(object) } /** * @brief initialize a list * * @param l list to be initialized */ rt_inline void rt_list_init(rt_list_t *l) { l->next = l->prev = l; } /** * @brief insert a node after a list * * @param l list to insert it * @param n new node to be inserted */ rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n) { l->next->prev = n; n->next = l->next; l->next = n; n->prev = l; } /** * @brief insert a node before a list * * @param n new node to be inserted * @param l list to insert it */ rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n) { l->prev->next = n; n->prev = l->prev; l->prev = n; n->next = l; } /** * @brief remove node from list. * @param n the node to remove from the list. */ rt_inline void rt_list_remove(rt_list_t *n) { n->next->prev = n->prev; n->prev->next = n->next; n->next = n->prev = n; } /** * @brief tests whether a list is empty * @param l the list to test. */ rt_inline int rt_list_isempty(const rt_list_t *l) { return l->next == l; } /** * @brief get the list length * @param l the list to get. */ rt_inline unsigned int rt_list_len(const rt_list_t *l) { unsigned int len = 0; const rt_list_t *p = l; while (p->next != l) { p = p->next; len ++; } return len; } /** * @brief get the struct for this entry * @param node the entry point * @param type the type of structure * @param member the name of list in structure */ #define rt_list_entry(node, type, member) \ rt_container_of(node, type, member) /** * rt_list_for_each - iterate over a list * @param pos the rt_list_t * to use as a loop cursor. * @param head the head for your list. */ #define rt_list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /** * rt_list_for_each_safe - iterate over a list safe against removal of list entry * @param pos the rt_list_t * to use as a loop cursor. * @param n another rt_list_t * to use as temporary storage * @param head the head for your list. */ #define rt_list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) /** * rt_list_for_each_entry - iterate over list of given type * @param pos the type * to use as a loop cursor. * @param head the head for your list. * @param member the name of the list_struct within the struct. */ #define rt_list_for_each_entry(pos, head, member) \ for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member); \ &pos->member != (head); \ pos = rt_list_entry(pos->member.next, rt_typeof(*pos), member)) /** * rt_list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @param pos the type * to use as a loop cursor. * @param n another type * to use as temporary storage * @param head the head for your list. * @param member the name of the list_struct within the struct. */ #define rt_list_for_each_entry_safe(pos, n, head, member) \ for (pos = rt_list_entry((head)->next, rt_typeof(*pos), member), \ n = rt_list_entry(pos->member.next, rt_typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = rt_list_entry(n->member.next, rt_typeof(*n), member)) /** * rt_list_first_entry - get the first element from a list * @param ptr the list head to take the element from. * @param type the type of the struct this is embedded in. * @param member the name of the list_struct within the struct. * * Note, that list is expected to be not empty. */ #define rt_list_first_entry(ptr, type, member) \ rt_list_entry((ptr)->next, type, member) #define RT_SLIST_OBJECT_INIT(object) { RT_NULL } /** * @brief initialize a single list * * @param l the single list to be initialized */ rt_inline void rt_slist_init(rt_slist_t *l) { l->next = RT_NULL; } rt_inline void rt_slist_append(rt_slist_t *l, rt_slist_t *n) { struct rt_slist_node *node; node = l; while (node->next) node = node->next; /* append the node to the tail */ node->next = n; n->next = RT_NULL; } rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n) { n->next = l->next; l->next = n; } rt_inline unsigned int rt_slist_len(const rt_slist_t *l) { unsigned int len = 0; const rt_slist_t *list = l->next; while (list != RT_NULL) { list = list->next; len ++; } return len; } rt_inline rt_slist_t *rt_slist_pop(rt_slist_t *l) { struct rt_slist_node *node = l; /* remove node */ node = node->next; if (node != (rt_slist_t *)0) { ((struct rt_slist_node *)l)->next = node->next; } return node; } rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n) { /* remove slist head */ struct rt_slist_node *node = l; while (node->next && node->next != n) node = node->next; /* remove node */ if (node->next != (rt_slist_t *)0) node->next = node->next->next; return l; } rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l) { return l->next; } rt_inline rt_slist_t *rt_slist_tail(rt_slist_t *l) { while (l->next) l = l->next; return l; } rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n) { return n->next; } rt_inline int rt_slist_isempty(rt_slist_t *l) { return l->next == RT_NULL; } /** * @brief get the struct for this single list node * @param node the entry point * @param type the type of structure * @param member the name of list in structure */ #define rt_slist_entry(node, type, member) \ rt_container_of(node, type, member) /** * rt_slist_for_each - iterate over a single list * @param pos the rt_slist_t * to use as a loop cursor. * @param head the head for your single list. */ #define rt_slist_for_each(pos, head) \ for (pos = (head)->next; pos != RT_NULL; pos = pos->next) /** * rt_slist_for_each_entry - iterate over single list of given type * @param pos the type * to use as a loop cursor. * @param head the head for your single list. * @param member the name of the list_struct within the struct. */ #define rt_slist_for_each_entry(pos, head, member) \ for (pos = ((head)->next == (RT_NULL) ? (RT_NULL) : rt_slist_entry((head)->next, rt_typeof(*pos), member)); \ pos != (RT_NULL) && &pos->member != (RT_NULL); \ pos = (pos->member.next == (RT_NULL) ? (RT_NULL) : rt_slist_entry(pos->member.next, rt_typeof(*pos), member))) /** * rt_slist_first_entry - get the first element from a slist * @param ptr the slist head to take the element from. * @param type the type of the struct this is embedded in. * @param member the name of the slist_struct within the struct. * * Note, that slist is expected to be not empty. */ #define rt_slist_first_entry(ptr, type, member) \ rt_slist_entry((ptr)->next, type, member) /** * rt_slist_tail_entry - get the tail element from a slist * @param ptr the slist head to take the element from. * @param type the type of the struct this is embedded in. * @param member the name of the slist_struct within the struct. * * Note, that slist is expected to be not empty. */ #define rt_slist_tail_entry(ptr, type, member) \ rt_slist_entry(rt_slist_tail(ptr), type, member) /**@}*/ #ifdef __cplusplus } #endif #endif