Motr  M0
tlist.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2011-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/ub.h"
24 #include "ut/ut.h"
25 #include "lib/types.h" /* uint64_t */
26 #include "lib/tlist.h"
27 
28 struct foo {
29  uint64_t f_payload;
30  uint64_t f_magic;
34 };
35 
36 enum {
37  N = 6,
38  NR = 128
39 };
40 
41 enum {
42  fl0_magix = 0xab5ce55edba1b0a0
43 };
44 
45 static const struct m0_tl_descr fl0 = M0_TL_DESCR("foo-s of bar",
46  struct foo,
47  f_linkage0,
48  f_magic,
49  fl0_magix,
50  0xba1dba11adba0bab);
51 
52 static const struct m0_tl_descr fl1 = M0_TL_DESCR("other foo-s of bar",
53  struct foo,
54  f_linkage1,
55  f_magic,
56  0xab5ce55edba1b0a0,
57  0xbabe1b0ccacc1078);
58 
59 static const struct m0_tl_descr fl2 = M0_TL_DESCR("unchecked foo-s of bar",
60  struct foo,
61  f_linkage2,
62  f_magic,
63  0,
64  0x0123456789abcdef);
65 
66 static struct m0_tl head0[N];
67 static struct m0_tl head1[N];
68 static struct m0_tl head2[N];
69 static struct foo amb[NR];
70 
71 struct bar {
72  uint64_t b_payload;
74  uint64_t b_magic;
75 };
76 
77 M0_TL_DESCR_DEFINE(bar, "bar-s", static, struct bar, b_linkage,
78  b_magic, 0xbeda551edcaca0ff, 0x7777777777777777);
79 M0_TL_DEFINE(bar, static, struct bar);
80 
81 static struct m0_tl bhead;
82 static struct bar B[NR];
83 
84 void test_tlist(void)
85 {
86  int i;
87  struct foo *obj;
88  struct m0_tl *head;
89  uint64_t sum;
90  uint64_t sumB;
91  uint64_t sum1;
92  bool done;
93  struct bar *b;
94 
96  /* link magic must be the same as in fl0, because the same ambient
97  object is shared. */
99 
100  /* initialise */
101 
102  sum = 0;
103  for (i = 0; i < ARRAY_SIZE(head0); ++i) {
104  m0_tlist_init(&fl0, &head0[i]);
105  m0_tlist_init(&fl1, &head1[i]);
106  m0_tlist_init(&fl2, &head2[i]);
107  }
108  for (i = 0, obj = amb; i < ARRAY_SIZE(amb); ++i, ++obj) {
109  m0_tlink_init(&fl0, obj);
110  m0_tlink_init(&fl1, obj);
111  m0_tlink_init(&fl2, obj);
112  obj->f_payload = i;
113  sum += i;
114  }
115 
116  for (i = 0; i < ARRAY_SIZE(head0); ++i) {
119 
122 
125  }
126 
127  /* insert foo-s in the lists */
128 
129  for (i = 0, obj = amb; i < ARRAY_SIZE(amb); ++i, ++obj) {
133  m0_tlist_add(&fl0, &head0[0], obj);
137  m0_tlist_add_tail(&fl1, &head1[0], obj);
141  m0_tlist_add_tail(&fl2, &head2[0], obj);
145 
148  }
152 
154  ((struct foo *)o)->f_magic == fl0_magix));
155 
156  /* initialise bar-s */
157 
158  bar_tlist_init(&bhead);
159  sumB = 0;
160  for (i = 0, b = B; i < ARRAY_SIZE(B); ++i, ++b) {
161  bar_tlink_init(b);
162  M0_UT_ASSERT(!bar_tlink_is_in(b));
163  bar_tlist_add(&bhead, b);
164  M0_UT_ASSERT(bar_tlink_is_in(b));
165  M0_UT_ASSERT(bar_tlist_contains(&bhead, b));
166  sumB += (b->b_payload = 3*i);
167  }
168 
169  M0_UT_ASSERT(bar_tlist_length(&bhead) == ARRAY_SIZE(B));
170  M0_UT_ASSERT(m0_tl_forall(bar, bb, &bhead, bb->b_payload % 3 == 0));
171 
172  /* check that everything is in the lists */
173 
174  sum1 = 0;
175  m0_tlist_for(&fl0, &head0[0], obj) {
176  sum1 += obj->f_payload;
177  } m0_tlist_endfor;
178 
179  M0_UT_ASSERT(sum == sum1);
180 
181  sum1 = 0;
182  m0_tlist_for(&fl1, &head1[0], obj)
183  sum1 += obj->f_payload;
185  M0_UT_ASSERT(sum == sum1);
186 
187  /* bulldozer the foo-s to the last head */
188 
189  for (head = head0, i = 0; i < N - 1; ++i, ++head) {
190  int j;
191 
193  for (j = 0; (obj = m0_tlist_head(&fl0, head)) != NULL; ++j)
194  m0_tlist_move_tail(&fl0, head + 1 + j % (N-i-1), obj);
196  }
197 
198  /* check that everything is still here */
199 
201  sum1 = 0;
203  sum1 += obj->f_payload;
205  M0_UT_ASSERT(sum == sum1);
206 
207  /* check that m0_tlist_for() works fine when the list is mutated */
208 
209  m0_tlist_for(&fl1, &head1[0], obj) {
210  if (obj->f_payload % 2 == 0)
211  m0_tlist_move(&fl1, &head1[1], obj);
212  } m0_tlist_endfor;
213 
214  m0_tlist_for(&fl1, &head1[0], obj) {
215  if (obj->f_payload % 2 != 0)
216  m0_tlist_move(&fl1, &head1[1], obj);
217  } m0_tlist_endfor;
218 
219  M0_UT_ASSERT(m0_tlist_length(&fl1, &head1[0]) == 0);
221 
222  head = &head1[1];
223 
224  /* bubble sort the list */
225 
226  do {
227  struct foo *prev;
228 
229  done = true;
230 
231  m0_tlist_for(&fl1, head, obj) {
232  prev = m0_tlist_prev(&fl1, head, obj);
233  if (prev != NULL && prev->f_payload > obj->f_payload) {
234  m0_tlist_del(&fl1, obj);
235  m0_tlist_add_before(&fl1, prev, obj);
236  done = false;
237  }
238  } m0_tlist_endfor;
239  } while (!done);
240 
241  /* check that the list is sorted */
242 
243  m0_tlist_for(&fl1, head, obj) {
244  struct foo *nxt = m0_tlist_next(&fl1, head, obj);
245  M0_UT_ASSERT(ergo(nxt != NULL,
246  obj->f_payload <= nxt->f_payload));
247  } m0_tlist_endfor;
248 
249  /* check that magic-less iteration works. */
250 
251  sum1 = 0;
252  m0_tlist_for(&fl2, &head2[0], obj)
253  sum1 += obj->f_payload;
255  M0_UT_ASSERT(sum == sum1);
256 
257  /* reverse bar-s */
258 
259  m0_tl_for(bar, &bhead, b) {
260  bar_tlist_move(&bhead, b);
261  } m0_tl_endfor;
262 
263  /* check that bar list is reversed */
264 
265  for (i = 0, b = bar_tlist_head(&bhead); b != NULL;
266  b = bar_tlist_next(&bhead, b), ++i) {
267  M0_UT_ASSERT(b->b_payload == 3*i);
268  }
269 
270  /* finalise */
271 
272  for (i = 0, obj = amb; i < ARRAY_SIZE(amb); ++i, ++obj) {
273  m0_tlist_del(&fl2, obj);
274  m0_tlist_del(&fl1, obj);
275  m0_tlist_del(&fl0, obj);
276  m0_tlink_fini(&fl2, obj);
277  m0_tlink_fini(&fl1, obj);
278  m0_tlink_fini(&fl0, obj);
279  obj->f_magic = 0;
280  }
281 
282  for (i = 0; i < ARRAY_SIZE(head0); ++i) {
283  m0_tlist_fini(&fl2, &head2[i]);
284  m0_tlist_fini(&fl1, &head1[i]);
285  m0_tlist_fini(&fl0, &head0[i]);
286  }
287 
288  for (i = 0, b = B; i < ARRAY_SIZE(B); ++i, ++b) {
289  bar_tlist_del(b);
290  bar_tlink_fini(b);
291  }
292 
293  bar_tlist_fini(&bhead);
294 }
295 
296 enum {
297  UB_ITER = 100000
298 };
299 
300 static struct foo t[UB_ITER];
301 static struct m0_tl list;
302 static struct foo *obj;
303 
304 static int ub_init(const char *opts M0_UNUSED)
305 {
306  int i;
307 
308  for (i = 0, obj = t; i < ARRAY_SIZE(t); ++i, ++obj)
309  m0_tlink_init(&fl0, obj);
310  m0_tlist_init(&fl0, &list);
311  return 0;
312 }
313 
314 static void ub_fini(void)
315 {
316  int i;
317 
318  m0_tlist_fini(&fl0, &list);
319  for (i = 0, obj = t; i < ARRAY_SIZE(t); ++i, ++obj)
320  m0_tlink_fini(&fl0, obj);
321 }
322 
323 static void ub_insert(int i)
324 {
325  m0_tlist_add(&fl0, &list, &t[i]);
326 }
327 
328 static void ub_delete(int i)
329 {
330  m0_tlist_del(&fl0, &t[i]);
331 }
332 
334  .us_name = "tlist-ub",
335  .us_init = ub_init,
336  .us_fini = ub_fini,
337  .us_run = {
338  { .ub_name = "insert",
339  .ub_iter = UB_ITER,
340  .ub_round = ub_insert },
341 
342  { .ub_name = "delete",
343  .ub_iter = UB_ITER,
344  .ub_round = ub_delete },
345 
346  { .ub_name = NULL }
347  }
348 };
349 
350 /*
351  * Local variables:
352  * c-indentation-style: "K&R"
353  * c-basic-offset: 8
354  * tab-width: 8
355  * fill-column: 80
356  * scroll-step: 1
357  * End:
358  */
static struct foo t[UB_ITER]
Definition: tlist.c:300
static struct m0_tl head0[N]
Definition: tlist.c:66
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
Definition: module.c:324
#define ergo(a, b)
Definition: misc.h:293
struct m0_tlink f_linkage1
Definition: tlist.c:32
Definition: bob.c:32
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
#define M0_CASSERT(cond)
void * f_payload
Definition: bob.c:33
M0_INTERNAL void m0_tlist_init(const struct m0_tl_descr *d, struct m0_tl *list)
Definition: tlist.c:46
static int sum
Definition: rwlock.c:53
M0_INTERNAL void m0_tlist_fini(const struct m0_tl_descr *d, struct m0_tl *list)
Definition: tlist.c:53
static struct m0_tl head2[N]
Definition: tlist.c:68
static const struct m0_tl_descr fl1
Definition: tlist.c:52
static struct foo * obj
Definition: tlist.c:302
static void ub_insert(int i)
Definition: tlist.c:323
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_tl_endfor
Definition: tlist.h:700
static int head(struct m0_sm *mach)
Definition: sm.c:468
Definition: hash.c:34
int i
Definition: dir.c:1033
M0_TL_DEFINE(bar, static, struct bar)
static const struct m0_tl_descr fl0
Definition: tlist.c:45
static void ub_fini(void)
Definition: tlist.c:314
M0_INTERNAL void * m0_tlist_prev(const struct m0_tl_descr *d, const struct m0_tl *list, const void *obj)
Definition: tlist.c:227
#define M0_ASSERT(cond)
const char * us_name
Definition: ub.h:76
static struct m0_tl list
Definition: tlist.c:301
uint64_t f_payload
Definition: tlist.c:29
Definition: tlist.h:251
#define M0_TL_DESCR(name, ambient_type, link_field, link_magic_field, link_magic, head_magic)
Definition: tlist.h:231
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
Definition: tlist.c:38
uint64_t b_payload
Definition: tlist.c:72
M0_INTERNAL void m0_tlist_move_tail(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:179
Definition: tlist.c:297
M0_INTERNAL size_t m0_tlist_length(const struct m0_tl_descr *d, const struct m0_tl *list)
Definition: tlist.c:117
uint64_t td_link_magic
Definition: tlist.h:221
Definition: tlist.c:37
static const struct m0_tl_descr fl2
Definition: tlist.c:59
struct m0_tlink f_linkage2
Definition: tlist.c:33
M0_INTERNAL void m0_tlink_init(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:63
static void ub_delete(int i)
Definition: tlist.c:328
uint64_t f_magic
Definition: hash.c:43
#define m0_tlist_forall(descr, var, head,...)
Definition: tlist.h:458
M0_INTERNAL bool m0_tlink_is_in(const struct m0_tl_descr *d, const void *obj)
Definition: tlist.c:103
struct m0_tlink b_linkage
Definition: tlist.c:73
void test_tlist(void)
Definition: tlist.c:84
static struct bar B[NR]
Definition: tlist.c:82
M0_TL_DESCR_DEFINE(bar, "bar-s", static, struct bar, b_linkage, b_magic, 0xbeda551edcaca0ff, 0x7777777777777777)
static struct m0_tl bhead
Definition: tlist.c:81
uint64_t b_magic
Definition: hash.c:36
static int ub_init(const char *opts M0_UNUSED)
Definition: tlist.c:304
#define m0_tlist_endfor
Definition: tlist.h:448
struct m0_ub_set m0_tlist_ub
Definition: tlist.c:333
static unsigned done
Definition: storage.c:91
#define m0_tlist_for(descr, head, obj)
Definition: tlist.h:435
struct m0_tlink f_linkage0
Definition: tlist.c:31
static struct m0_tl head1[N]
Definition: tlist.c:67
M0_INTERNAL void m0_tlist_move(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:170
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
M0_INTERNAL bool m0_tlist_contains(const struct m0_tl_descr *d, const struct m0_tl *list, const void *obj)
Definition: tlist.c:109
#define ARRAY_SIZE(a)
Definition: misc.h:45
Definition: ub.h:74
#define M0_UT_ASSERT(a)
Definition: ut.h:46
M0_INTERNAL void m0_tlist_add_tail(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:133
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735
#define M0_UNUSED
Definition: misc.h:380