xref: /spdk/lib/env_ocf/ocf_env_list.h (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #ifndef __OCF_LIST_H__
7 #define __OCF_LIST_H__
8 
9 #define LIST_POISON1  ((void *) 0x00100100)
10 #define LIST_POISON2  ((void *) 0x00200200)
11 
12 /**
13  * List entry structure mimicking linux kernel based one.
14  */
15 struct list_head {
16 	struct list_head *next;
17 	struct list_head *prev;
18 } __attribute__((aligned(64)));
19 
20 /**
21  * start an empty list
22  */
23 #define INIT_LIST_HEAD(l) { (l)->prev = l; (l)->next = l; }
24 
25 /**
26  * Add item to list head.
27  * @param it list entry to be added
28  * @param l1 list main node (head)
29  */
30 static inline void
list_add(struct list_head * it,struct list_head * l1)31 list_add(struct list_head *it, struct list_head *l1)
32 {
33 	it->prev = l1;
34 	it->next = l1->next;
35 
36 	l1->next->prev = it;
37 	l1->next = it;
38 }
39 
40 /**
41  * Add item it to tail.
42  * @param it list entry to be added
43  * @param l1 list main node (head)
44  */
45 static inline void
list_add_tail(struct list_head * it,struct list_head * l1)46 list_add_tail(struct list_head *it, struct list_head *l1)
47 {
48 	it->prev = l1->prev;
49 	it->next = l1;
50 
51 	l1->prev->next = it;
52 	l1->prev = it;
53 }
54 
55 /**
56  * check if a list is empty (return true)
57  */
58 static inline int
list_empty(struct list_head * it)59 list_empty(struct list_head *it)
60 {
61 	return it->next == it;
62 }
63 
64 /**
65  * delete an entry from a list
66  */
67 static inline void
list_del(struct list_head * it)68 list_del(struct list_head *it)
69 {
70 	it->next->prev = it->prev;
71 	it->prev->next = it->next;
72 }
73 
74 static inline void
list_move_tail(struct list_head * list,struct list_head * head)75 list_move_tail(struct list_head *list,
76 	       struct list_head *head)
77 {
78 	list_del(list);
79 	list_add_tail(list, head);
80 }
81 
82 static inline void
list_move(struct list_head * list,struct list_head * head)83 list_move(struct list_head *list,
84 	  struct list_head *head)
85 {
86 	list_del(list);
87 	list_add(list, head);
88 }
89 
90 /**
91  * Extract an entry.
92  * @param list_head_i list head item, from which entry is extracted
93  * @param item_type type (struct) of list entry
94  * @param field_name name of list_head field within item_type
95  */
96 #define list_entry(list_head_i, item_type, field_name) \
97 	(item_type *)(((void*)(list_head_i)) - offsetof(item_type, field_name))
98 
99 #define list_first_entry(list_head_i, item_type, field_name) \
100 	list_entry((list_head_i)->next, item_type, field_name)
101 
102 /**
103  * @param iterator uninitialized list_head pointer, to be used as iterator
104  * @param plist list head (main node)
105  */
106 #define list_for_each(iterator, plist) \
107 	for (iterator = (plist)->next; \
108 	     (iterator)->next != (plist)->next; \
109 	     iterator = (iterator)->next)
110 
111 /**
112  * Safe version of list_for_each which works even if entries are deleted during
113  * loop.
114  * @param iterator uninitialized list_head pointer, to be used as iterator
115  * @param q another uninitialized list_head, used as helper
116  * @param plist list head (main node)
117  */
118 /*
119  * Algorithm handles situation, where q is deleted.
120  * consider in example 3 element list with header h:
121  *
122  *   h -> 1 -> 2 -> 3 ->
123  *1.      i    q
124  *
125  *2.           i    q
126  *
127  *3. q              i
128  */
129 #define list_for_each_safe(iterator, q, plist) \
130 	for (iterator = (q = (plist)->next->next)->prev; \
131 	     (q) != (plist)->next; \
132 	     iterator = (q = (q)->next)->prev)
133 
134 #define _list_entry_helper(item, head, field_name) list_entry(head, typeof(*item), field_name)
135 
136 /**
137  * Iterate over list entries.
138  * @param list pointer to list item (iterator)
139  * @param plist pointer to list_head item
140  * @param field_name name of list_head field in list entry
141  */
142 #define list_for_each_entry(item, plist, field_name) \
143 	for (item = _list_entry_helper(item, (plist)->next, field_name); \
144 	     _list_entry_helper(item, (item)->field_name.next, field_name) !=\
145 		     _list_entry_helper(item, (plist)->next, field_name); \
146 	     item = _list_entry_helper(item, (item)->field_name.next, field_name))
147 
148 /**
149  * Safe version of list_for_each_entry which works even if entries are deleted
150  * during loop.
151  * @param list pointer to list item (iterator)
152  * @param q another pointer to list item, used as helper
153  * @param plist pointer to list_head item
154  * @param field_name name of list_head field in list entry
155  */
156 #define list_for_each_entry_safe(item, q, plist, field_name)		\
157 	for (item = _list_entry_helper(item, (plist)->next, field_name), \
158 	     q = _list_entry_helper(item, (item)->field_name.next, field_name); \
159 	     _list_entry_helper(item, (item)->field_name.next, field_name) != \
160 		     _list_entry_helper(item, (plist)->next, field_name); \
161 	     item = q, q = _list_entry_helper(q, (q)->field_name.next, field_name))
162 
163 #endif
164