Motr  M0
tlist.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/tlist.h"
24 
33 static struct m0_list_link *__link(const struct m0_tl_descr *d,
34  const void *obj);
35 
39 static uint64_t magic(const struct m0_tl_descr *d, const void *obj);
40 
44 static void *amb(const struct m0_tl_descr *d, struct m0_list_link *link);
45 
46 M0_INTERNAL void m0_tlist_init(const struct m0_tl_descr *d, struct m0_tl *list)
47 {
51 }
52 
53 M0_INTERNAL void m0_tlist_fini(const struct m0_tl_descr *d, struct m0_tl *list)
54 {
57  /*
58  * We don't unset the magic field (list->t_magic), because it can be
59  * shared by multiple tlinks embedded in the same ambient object.
60  */
61 }
62 
63 M0_INTERNAL void m0_tlink_init(const struct m0_tl_descr *d, void *obj)
64 {
66  if (d->td_link_magic != 0)
67  *(uint64_t *)(obj + d->td_link_magic_offset) = d->td_link_magic;
69 }
70 
71 M0_INTERNAL void m0_tlink_init_at(const struct m0_tl_descr *d, void *obj,
72  struct m0_tl *list)
73 {
74  m0_tlink_init(d, obj);
75  m0_tlist_add(d, list, obj);
76 }
77 
78 M0_INTERNAL void m0_tlink_init_at_tail(const struct m0_tl_descr *d, void *obj,
79  struct m0_tl *list)
80 {
81  m0_tlink_init(d, obj);
83 }
84 
85 M0_INTERNAL void m0_tlink_fini(const struct m0_tl_descr *d, void *obj)
86 {
88 }
89 
90 M0_INTERNAL void m0_tlink_del_fini(const struct m0_tl_descr *d, void *obj)
91 {
92  m0_tlist_del(d, obj);
93  m0_tlink_fini(d, obj);
94 }
95 
96 M0_INTERNAL bool m0_tlist_is_empty(const struct m0_tl_descr *d,
97  const struct m0_tl *list)
98 {
100  return m0_list_is_empty(&list->t_head);
101 }
102 
103 M0_INTERNAL bool m0_tlink_is_in(const struct m0_tl_descr *d, const void *obj)
104 {
106  return m0_list_link_is_in(__link(d, obj));
107 }
108 
109 M0_INTERNAL bool m0_tlist_contains(const struct m0_tl_descr *d,
110  const struct m0_tl *list, const void *obj)
111 {
114  return m0_list_contains(&list->t_head, __link(d, obj));
115 }
116 
117 M0_INTERNAL size_t m0_tlist_length(const struct m0_tl_descr *d,
118  const struct m0_tl *list)
119 {
121  return m0_list_length(&list->t_head);
122 }
123 M0_EXPORTED(m0_tlist_length);
124 
125 M0_INTERNAL void m0_tlist_add(const struct m0_tl_descr *d, struct m0_tl *list,
126  void *obj)
127 {
129  M0_PRE(!m0_tlink_is_in(d, obj));
130  m0_list_add(&list->t_head, __link(d, obj));
131 }
132 
133 M0_INTERNAL void m0_tlist_add_tail(const struct m0_tl_descr *d,
134  struct m0_tl *list, void *obj)
135 {
137  M0_PRE(!m0_tlink_is_in(d, obj));
139 }
140 
141 M0_INTERNAL void m0_tlist_add_after(const struct m0_tl_descr *d, void *obj,
142  void *new)
143 {
145  M0_PRE(!m0_tlink_is_in(d, new));
146  m0_list_add_after(__link(d, obj), __link(d, new));
147 }
148 
149 M0_INTERNAL void m0_tlist_add_before(const struct m0_tl_descr *d, void *obj,
150  void *new)
151 {
153  M0_PRE(!m0_tlink_is_in(d, new));
154  m0_list_add_before(__link(d, obj), __link(d, new));
155 }
156 
157 M0_INTERNAL void m0_tlist_del(const struct m0_tl_descr *d, void *obj)
158 {
160  m0_tlist_remove(d, obj);
161 }
162 
163 M0_INTERNAL void m0_tlist_remove(const struct m0_tl_descr *d, void *obj)
164 {
166  m0_list_del(__link(d, obj));
167  M0_PRE(!m0_tlink_is_in(d, obj));
168 }
169 
170 M0_INTERNAL void m0_tlist_move(const struct m0_tl_descr *d, struct m0_tl *list,
171  void *obj)
172 {
175 
177 }
178 
179 M0_INTERNAL void m0_tlist_move_tail(const struct m0_tl_descr *d,
180  struct m0_tl *list, void *obj)
181 {
183 
185 }
186 
187 void *m0_tlist_head(const struct m0_tl_descr *d, const struct m0_tl *list)
188 {
189  const struct m0_list *head;
190 
192 
193  head = &list->t_head;
194  return m0_list_is_empty(head) ? NULL : amb(d, head->l_head);
195 }
196 
197 M0_INTERNAL void *m0_tlist_pop(const struct m0_tl_descr *d,
198  const struct m0_tl *list)
199 {
200  void *head = m0_tlist_head(d, list);
201 
202  if (head != NULL)
203  m0_tlist_del(d, head);
204  return head;
205 }
206 
207 M0_INTERNAL void *m0_tlist_tail(const struct m0_tl_descr *d,
208  const struct m0_tl *list)
209 {
210  const struct m0_list *head;
211 
213 
214  head = &list->t_head;
215  return head->l_tail != (void *)head ? amb(d, head->l_tail) : NULL;
216 }
217 
218 void *m0_tlist_next(const struct m0_tl_descr *d,
219  const struct m0_tl *list, const void *obj)
220 {
221  struct m0_list_link *next;
222 
223  next = __link(d, obj)->ll_next;
224  return (void *)next != &list->t_head ? amb(d, next) : NULL;
225 }
226 
227 M0_INTERNAL void *m0_tlist_prev(const struct m0_tl_descr *d,
228  const struct m0_tl *list, const void *obj)
229 {
230  struct m0_list_link *prev;
231 
232  prev = __link(d, obj)->ll_prev;
233  return (void *)prev != &list->t_head ? amb(d, prev) : NULL;
234 }
235 
236 M0_INTERNAL bool m0_tlist_invariant(const struct m0_tl_descr *d,
237  const struct m0_tl *list)
238 {
239  const struct m0_list_link *head;
240  struct m0_list_link *scan;
241 
242  head = (void *)&list->t_head;
243 
244  if (list->t_magic != d->td_head_magic)
245  return false;
246  if ((list->t_head.l_head == head) != (list->t_head.l_tail == head))
247  return false;
248 
249  for (scan = list->t_head.l_head; scan != head; scan = scan->ll_next) {
250  if (scan->ll_next->ll_prev != scan ||
251  scan->ll_prev->ll_next != scan)
252  return false;
253  if (!M0_CHECK_EX(m0_tlink_invariant(d, amb(d, scan))))
254  return false;
255  }
256  return true;
257 }
258 
259 M0_INTERNAL bool m0_tlist_invariant_ext(const struct m0_tl_descr *d,
260  const struct m0_tl *list,
261  bool (*check)(const void *, void *),
262  void *datum)
263 {
264  if (m0_tlist_invariant(d, list)) {
265  void *obj;
266 
267  m0_tlist_for(d, (struct m0_tl *)list, obj) {
268  if (!check(obj, datum))
269  return false;
270  } m0_tlist_endfor;
271  }
272  return true;
273 }
274 
275 M0_INTERNAL bool m0_tlink_invariant(const struct m0_tl_descr *d,
276  const void *obj)
277 {
278  return d->td_link_magic == 0 || magic(d, obj) == d->td_link_magic;
279 }
280 
281 static struct m0_list_link *__link(const struct m0_tl_descr *d, const void *obj)
282 {
283  return &((struct m0_tlink *)(obj + d->td_link_offset))->t_link;
284 }
285 
286 static uint64_t magic(const struct m0_tl_descr *d, const void *obj)
287 {
288  return *(uint64_t *)(obj + d->td_link_magic_offset);
289 }
290 
291 static void *amb(const struct m0_tl_descr *d, struct m0_list_link *link)
292 {
293  return (void *)container_of(link, struct m0_tlink,
294  t_link) - d->td_link_offset;
295 }
296 
299 /*
300  * Local variables:
301  * c-indentation-style: "K&R"
302  * c-basic-offset: 8
303  * tab-width: 8
304  * fill-column: 80
305  * scroll-step: 1
306  * End:
307  */
M0_INTERNAL void m0_list_link_fini(struct m0_list_link *link)
Definition: list.c:176
#define M0_PRE(cond)
M0_INTERNAL void m0_list_add(struct m0_list *head, struct m0_list_link *new)
Definition: list.c:113
int td_link_magic_offset
Definition: tlist.h:215
void * m0_tlist_head(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:187
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_list_add_before(struct m0_list_link *anchor, struct m0_list_link *new)
Definition: list.c:133
M0_INTERNAL void m0_list_init(struct m0_list *head)
Definition: list.c:29
struct m0_list_link * l_tail
Definition: list.h:80
M0_INTERNAL void m0_tlist_add_before(const struct m0_tl_descr *d, void *obj, void *new)
Definition: tlist.c:149
M0_INTERNAL void m0_tlist_add(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:125
static uint64_t magic(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:286
M0_INTERNAL void m0_list_fini(struct m0_list *head)
Definition: list.c:36
M0_INTERNAL void m0_tlist_init(const struct m0_tl_descr *d, struct m0_tl *list)
Definition: tlist.c:46
uint64_t t_magic
Definition: tlist.h:256
M0_INTERNAL void m0_list_del(struct m0_list_link *old)
Definition: list.c:147
M0_INTERNAL void m0_tlist_fini(const struct m0_tl_descr *d, struct m0_tl *list)
Definition: tlist.c:53
#define container_of(ptr, type, member)
Definition: misc.h:33
static struct foo * obj
Definition: tlist.c:302
#define M0_INVARIANT_EX(cond)
M0_INTERNAL bool m0_tlist_is_empty(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:96
M0_INTERNAL void m0_tlist_del(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:157
#define M0_CHECK_EX(cond)
static int head(struct m0_sm *mach)
Definition: sm.c:468
struct m0_list t_head
Definition: tlist.h:258
M0_INTERNAL size_t m0_list_length(const struct m0_list *list)
Definition: list.c:75
struct m0_list_link * l_head
Definition: list.h:76
if(value==NULL)
Definition: dir.c:350
M0_INTERNAL void * m0_tlist_prev(const struct m0_tl_descr *d, const struct m0_tl *list, const void *obj)
Definition: tlist.c:227
static struct m0_tl list
Definition: tlist.c:301
Definition: tlist.h:251
static int next[]
Definition: cp.c:248
M0_INTERNAL void m0_tlink_fini(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:85
void * m0_tlist_next(const struct m0_tl_descr *d, const struct m0_tl *list, const void *obj)
Definition: tlist.c:218
M0_INTERNAL void m0_tlist_remove(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:163
M0_INTERNAL void m0_tlist_move_tail(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:179
static void * amb(const struct m0_tl_descr *d, struct m0_list_link *link)
Definition: tlist.c:291
M0_INTERNAL size_t m0_tlist_length(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:117
M0_INTERNAL bool m0_list_contains(const struct m0_list *list, const struct m0_list_link *link)
Definition: list.c:87
uint64_t td_link_magic
Definition: tlist.h:221
M0_INTERNAL bool m0_list_is_empty(const struct m0_list *head)
Definition: list.c:42
M0_INTERNAL void m0_tlink_init(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:63
uint64_t td_head_magic
Definition: tlist.h:226
M0_INTERNAL bool m0_list_link_is_in(const struct m0_list_link *link)
Definition: list.c:181
Definition: list.h:72
M0_INTERNAL bool m0_tlink_is_in(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:103
int td_link_offset
Definition: tlist.h:208
M0_INTERNAL void m0_tlink_init_at_tail(const struct m0_tl_descr *d, void *obj, struct m0_tl *list)
Definition: tlist.c:78
M0_INTERNAL bool m0_tlist_invariant(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:236
M0_INTERNAL void m0_list_add_after(struct m0_list_link *anchor, struct m0_list_link *new)
Definition: list.c:126
struct m0_list_link t_link
Definition: tlist.h:293
M0_INTERNAL void m0_tlink_init_at(const struct m0_tl_descr *d, void *obj, struct m0_tl *list)
Definition: tlist.c:71
#define m0_tlist_endfor
Definition: tlist.h:448
M0_INTERNAL void m0_list_move(struct m0_list *head, struct m0_list_link *old)
Definition: list.c:154
M0_INTERNAL void m0_list_move_tail(struct m0_list *head, struct m0_list_link *old)
Definition: list.c:161
void check(struct workload *w)
M0_INTERNAL void * m0_tlist_pop(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:197
#define m0_tlist_for(descr, head, obj)
Definition: tlist.h:435
M0_INTERNAL void m0_list_link_init(struct m0_list_link *link)
Definition: list.c:169
M0_INTERNAL void m0_list_add_tail(struct m0_list *head, struct m0_list_link *new)
Definition: list.c:119
M0_INTERNAL void m0_tlist_move(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:170
M0_INTERNAL void m0_tlist_add_after(const struct m0_tl_descr *d, void *obj, void *new)
Definition: tlist.c:141
M0_INTERNAL void * m0_tlist_tail(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:207
static int scan(struct scanner *s)
Definition: beck.c:963
M0_INTERNAL bool m0_tlist_contains(const struct m0_tl_descr *d, const struct m0_tl *list, const void *obj)
Definition: tlist.c:109
M0_INTERNAL bool m0_tlink_invariant(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:275
M0_INTERNAL void m0_tlist_add_tail(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:133
static struct m0_list_link * __link(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:281
M0_INTERNAL bool m0_tlist_invariant_ext(const struct m0_tl_descr *d, const struct m0_tl *list, bool(*check)(const void *, void *), void *datum)
Definition: tlist.c:259
M0_INTERNAL void m0_tlink_del_fini(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:90