1d5ac70f0Sopenharmony_ci/* Doubly linked list macros compatible with Linux kernel's version 2d5ac70f0Sopenharmony_ci * Copyright (c) 2015 by Takashi Iwai <tiwai@suse.de> 3d5ac70f0Sopenharmony_ci * 4d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 5d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 6d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 7d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 8d5ac70f0Sopenharmony_ci * 9d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 10d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 13d5ac70f0Sopenharmony_ci */ 14d5ac70f0Sopenharmony_ci 15d5ac70f0Sopenharmony_ci#ifndef _LIST_H 16d5ac70f0Sopenharmony_ci#define _LIST_H 17d5ac70f0Sopenharmony_ci 18d5ac70f0Sopenharmony_ci#include <stddef.h> 19d5ac70f0Sopenharmony_ci 20d5ac70f0Sopenharmony_cistruct list_head { 21d5ac70f0Sopenharmony_ci struct list_head *next; 22d5ac70f0Sopenharmony_ci struct list_head *prev; 23d5ac70f0Sopenharmony_ci}; 24d5ac70f0Sopenharmony_ci 25d5ac70f0Sopenharmony_ci/* one-shot definition of a list head */ 26d5ac70f0Sopenharmony_ci#define LIST_HEAD(x) \ 27d5ac70f0Sopenharmony_ci struct list_head x = { &x, &x } 28d5ac70f0Sopenharmony_ci 29d5ac70f0Sopenharmony_ci/* initialize a list head explicitly */ 30d5ac70f0Sopenharmony_cistatic inline void INIT_LIST_HEAD(struct list_head *p) 31d5ac70f0Sopenharmony_ci{ 32d5ac70f0Sopenharmony_ci p->next = p->prev = p; 33d5ac70f0Sopenharmony_ci} 34d5ac70f0Sopenharmony_ci 35d5ac70f0Sopenharmony_ci#define list_entry_offset(p, type, offset) \ 36d5ac70f0Sopenharmony_ci ((type *)((char *)(p) - (offset))) 37d5ac70f0Sopenharmony_ci 38d5ac70f0Sopenharmony_ci/* list_entry - retrieve the original struct from list_head 39d5ac70f0Sopenharmony_ci * @p: list_head pointer 40d5ac70f0Sopenharmony_ci * @type: struct type 41d5ac70f0Sopenharmony_ci * @member: struct field member containing the list_head 42d5ac70f0Sopenharmony_ci */ 43d5ac70f0Sopenharmony_ci#define list_entry(p, type, member) \ 44d5ac70f0Sopenharmony_ci list_entry_offset(p, type, offsetof(type, member)) 45d5ac70f0Sopenharmony_ci 46d5ac70f0Sopenharmony_ci/* list_for_each - iterate over the linked list 47d5ac70f0Sopenharmony_ci * @p: iterator, a list_head pointer variable 48d5ac70f0Sopenharmony_ci * @list: list_head pointer containing the list 49d5ac70f0Sopenharmony_ci */ 50d5ac70f0Sopenharmony_ci#define list_for_each(p, list) \ 51d5ac70f0Sopenharmony_ci for (p = (list)->next; p != (list); p = p->next) 52d5ac70f0Sopenharmony_ci 53d5ac70f0Sopenharmony_ci/* list_for_each_safe - iterate over the linked list, safe to delete 54d5ac70f0Sopenharmony_ci * @p: iterator, a list_head pointer variable 55d5ac70f0Sopenharmony_ci * @s: a temporary variable to keep the next, a list_head pointer, too 56d5ac70f0Sopenharmony_ci * @list: list_head pointer containing the list 57d5ac70f0Sopenharmony_ci */ 58d5ac70f0Sopenharmony_ci#define list_for_each_safe(p, s, list) \ 59d5ac70f0Sopenharmony_ci for (p = (list)->next; s = p->next, p != (list); p = s) 60d5ac70f0Sopenharmony_ci 61d5ac70f0Sopenharmony_ci/* list_add - prepend a list entry at the head 62d5ac70f0Sopenharmony_ci * @p: the new list entry to add 63d5ac70f0Sopenharmony_ci * @list: the list head 64d5ac70f0Sopenharmony_ci */ 65d5ac70f0Sopenharmony_cistatic inline void list_add(struct list_head *p, struct list_head *list) 66d5ac70f0Sopenharmony_ci{ 67d5ac70f0Sopenharmony_ci struct list_head *first = list->next; 68d5ac70f0Sopenharmony_ci 69d5ac70f0Sopenharmony_ci p->next = first; 70d5ac70f0Sopenharmony_ci first->prev = p; 71d5ac70f0Sopenharmony_ci list->next = p; 72d5ac70f0Sopenharmony_ci p->prev = list; 73d5ac70f0Sopenharmony_ci} 74d5ac70f0Sopenharmony_ci 75d5ac70f0Sopenharmony_ci/* list_add_tail - append a list entry at the tail 76d5ac70f0Sopenharmony_ci * @p: the new list entry to add 77d5ac70f0Sopenharmony_ci * @list: the list head 78d5ac70f0Sopenharmony_ci */ 79d5ac70f0Sopenharmony_cistatic inline void list_add_tail(struct list_head *p, struct list_head *list) 80d5ac70f0Sopenharmony_ci{ 81d5ac70f0Sopenharmony_ci struct list_head *last = list->prev; 82d5ac70f0Sopenharmony_ci 83d5ac70f0Sopenharmony_ci last->next = p; 84d5ac70f0Sopenharmony_ci p->prev = last; 85d5ac70f0Sopenharmony_ci p->next = list; 86d5ac70f0Sopenharmony_ci list->prev = p; 87d5ac70f0Sopenharmony_ci} 88d5ac70f0Sopenharmony_ci 89d5ac70f0Sopenharmony_ci/* list_insert - insert a new list entry between two known consecutive entries 90d5ac70f0Sopenharmony_ci * @p: the new entry to be inserted between prev and next 91d5ac70f0Sopenharmony_ci * @prev: the left-side entry 92d5ac70f0Sopenharmony_ci * @next: the right-side entry 93d5ac70f0Sopenharmony_ci */ 94d5ac70f0Sopenharmony_cistatic inline void list_insert(struct list_head *p, 95d5ac70f0Sopenharmony_ci struct list_head *prev, 96d5ac70f0Sopenharmony_ci struct list_head *next) 97d5ac70f0Sopenharmony_ci{ 98d5ac70f0Sopenharmony_ci next->prev = p; 99d5ac70f0Sopenharmony_ci p->next = next; 100d5ac70f0Sopenharmony_ci p->prev = prev; 101d5ac70f0Sopenharmony_ci prev->next = p; 102d5ac70f0Sopenharmony_ci} 103d5ac70f0Sopenharmony_ci 104d5ac70f0Sopenharmony_ci/* list_del - delete the given list entry */ 105d5ac70f0Sopenharmony_cistatic inline void list_del(struct list_head *p) 106d5ac70f0Sopenharmony_ci{ 107d5ac70f0Sopenharmony_ci p->prev->next = p->next; 108d5ac70f0Sopenharmony_ci p->next->prev = p->prev; 109d5ac70f0Sopenharmony_ci} 110d5ac70f0Sopenharmony_ci 111d5ac70f0Sopenharmony_ci/* list_empty - returns 1 if the given list is empty */ 112d5ac70f0Sopenharmony_cistatic inline int list_empty(const struct list_head *p) 113d5ac70f0Sopenharmony_ci{ 114d5ac70f0Sopenharmony_ci return p->next == p; 115d5ac70f0Sopenharmony_ci} 116d5ac70f0Sopenharmony_ci 117d5ac70f0Sopenharmony_ci#endif /* _LIST_H */ 118