Path: blob/main/sys/contrib/vchiq/interface/compat/list.h
48383 views
/* $NetBSD: list.h,v 1.5 2014/08/20 15:26:52 riastradh Exp $ */12/*-3* Copyright (c) 2013 The NetBSD Foundation, Inc.4* All rights reserved.5*6* This code is derived from software contributed to The NetBSD Foundation7* by Taylor R. Campbell.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS19* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED20* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS22* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR23* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF24* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS25* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN26* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)27* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE28* POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* Notes on porting:33*34* - LIST_HEAD(x) means a declaration `struct list_head x =35* LIST_HEAD_INIT(x)' in Linux, but something else in NetBSD.36* Replace by the expansion.37*38* - The `_rcu' routines here are not actually pserialize(9)-safe.39* They need dependent read memory barriers added. Please fix this40* if you need to use them with pserialize(9).41*/4243#ifndef _LINUX_LIST_H_44#define _LINUX_LIST_H_4546#include <sys/queue.h>4748#define container_of(ptr, type, member) \49({ \50__typeof(((type *)0)->member) *_p = (ptr); \51(type *)((char *)_p - offsetof(type, member)); \52})5354/*55* Doubly-linked lists.56*/5758struct list_head {59struct list_head *prev;60struct list_head *next;61};6263#define LIST_HEAD_INIT(name) { .prev = &(name), .next = &(name) }6465static inline void66INIT_LIST_HEAD(struct list_head *head)67{68head->prev = head;69head->next = head;70}7172static inline struct list_head *73list_first(const struct list_head *head)74{75return head->next;76}7778static inline struct list_head *79list_last(const struct list_head *head)80{81return head->prev;82}8384static inline struct list_head *85list_next(const struct list_head *node)86{87return node->next;88}8990static inline struct list_head *91list_prev(const struct list_head *node)92{93return node->prev;94}9596static inline int97list_empty(const struct list_head *head)98{99return (head->next == head);100}101102static inline int103list_is_singular(const struct list_head *head)104{105106if (list_empty(head))107return false;108if (head->next != head->prev)109return false;110return true;111}112113static inline void114__list_add_between(struct list_head *prev, struct list_head *node,115struct list_head *next)116{117prev->next = node;118node->prev = prev;119node->next = next;120next->prev = node;121}122123static inline void124list_add(struct list_head *node, struct list_head *head)125{126__list_add_between(head, node, head->next);127}128129static inline void130list_add_tail(struct list_head *node, struct list_head *head)131{132__list_add_between(head->prev, node, head);133}134135static inline void136list_del(struct list_head *entry)137{138entry->prev->next = entry->next;139entry->next->prev = entry->prev;140}141142static inline void143__list_splice_between(struct list_head *prev, const struct list_head *list,144struct list_head *next)145{146struct list_head *first = list->next;147struct list_head *last = list->prev;148149first->prev = prev;150prev->next = first;151152last->next = next;153next->prev = last;154}155156static inline void157list_splice(const struct list_head *list, struct list_head *head)158{159if (!list_empty(list))160__list_splice_between(head, list, head->next);161}162163static inline void164list_splice_tail(const struct list_head *list, struct list_head *head)165{166if (!list_empty(list))167__list_splice_between(head->prev, list, head);168}169170static inline void171list_move(struct list_head *node, struct list_head *head)172{173list_del(node);174list_add(node, head);175}176177static inline void178list_move_tail(struct list_head *node, struct list_head *head)179{180list_del(node);181list_add_tail(node, head);182}183184static inline void185list_replace(struct list_head *old, struct list_head *new)186{187new->prev = old->prev;188old->prev->next = new;189new->next = old->next;190old->next->prev = new;191}192193static inline void194list_del_init(struct list_head *node)195{196list_del(node);197INIT_LIST_HEAD(node);198}199200#define list_entry(PTR, TYPE, FIELD) container_of(PTR, TYPE, FIELD)201#define list_first_entry(PTR, TYPE, FIELD) \202list_entry(list_first((PTR)), TYPE, FIELD)203#define list_last_entry(PTR, TYPE, FIELD) \204list_entry(list_last((PTR)), TYPE, FIELD)205#define list_next_entry(ENTRY, FIELD) \206list_entry(list_next(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD)207#define list_prev_entry(ENTRY, FIELD) \208list_entry(list_prev(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD)209210#define list_for_each(VAR, HEAD) \211for ((VAR) = list_first((HEAD)); \212(VAR) != (HEAD); \213(VAR) = list_next((VAR)))214215#define list_for_each_safe(VAR, NEXT, HEAD) \216for ((VAR) = list_first((HEAD)); \217((VAR) != (HEAD)) && ((NEXT) = list_next((VAR)), 1); \218(VAR) = (NEXT))219220#define list_for_each_entry(VAR, HEAD, FIELD) \221for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \222&(VAR)->FIELD != (HEAD); \223(VAR) = list_entry(list_next(&(VAR)->FIELD), typeof(*(VAR)), \224FIELD))225226#define list_for_each_entry_reverse(VAR, HEAD, FIELD) \227for ((VAR) = list_entry(list_last((HEAD)), typeof(*(VAR)), FIELD); \228&(VAR)->FIELD != (HEAD); \229(VAR) = list_entry(list_prev(&(VAR)->FIELD), typeof(*(VAR)), \230FIELD))231232#define list_for_each_entry_safe(VAR, NEXT, HEAD, FIELD) \233for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \234(&(VAR)->FIELD != (HEAD)) && \235((NEXT) = list_entry(list_next(&(VAR)->FIELD), \236typeof(*(VAR)), FIELD), 1); \237(VAR) = (NEXT))238239#define list_for_each_entry_continue(VAR, HEAD, FIELD) \240for ((VAR) = list_next_entry((VAR), FIELD); \241&(VAR)->FIELD != (HEAD); \242(VAR) = list_next_entry((VAR), FIELD))243244#define list_for_each_entry_continue_reverse(VAR, HEAD, FIELD) \245for ((VAR) = list_prev_entry((VAR), FIELD); \246&(VAR)->FIELD != (HEAD); \247(VAR) = list_prev_entry((VAR), FIELD))248249#define list_for_each_entry_safe_from(VAR, NEXT, HEAD, FIELD) \250for (; \251(&(VAR)->FIELD != (HEAD)) && \252((NEXT) = list_next_entry((VAR), FIELD)); \253(VAR) = (NEXT))254255#endif /* _LINUX_LIST_H_ */256257258