source: doc/theses/mike_brooks_MMath/benchmarks/list/tailq-bug.c @ 0b66ef9

ADTast-experimental
Last change on this file since 0b66ef9 was 0b66ef9, checked in by Michael Brooks <mlbrooks@…>, 13 months ago

Add linked list performance experiment

  • Property mode set to 100644
File size: 3.4 KB
Line 
1/*
2
3There is a right way and a wrong way to remove the last element of a tailq.
4The right way does it in two steps.
5This fact is undocumented anywhere and never asked on SO.
6
7When the TAILQ_REMOVE is in an intermediate state of removal, it proceeds with a subsequent step starting from its "remove this guy" argument.
8So "remove this guy" must be fully evaluated to a concrete node (call by value).
9If you try to do it with nested expressions, this subsequent call of "from which guy again?" performs an evaluation of TAILQ_LAST in the intermediate state (call by name), which gives the wrong value.
10Everything then gets trashed.
11
12The actual/expected annotations are for the symptom that led me to the test.
13  actual means without -DFIXIT
14  expected obtains with -DFIXIT
15Other outputs are unannotated, but we can easily see things getting trashed in them too.
16
17*/
18
19
20#include <sys/queue.h>
21#include <stdio.h>
22
23#ifdef FIXIT
24#define MY_TAILQ_REMOVE_LAST(headp, TYPE, HEADNAME, NAME) ({\
25    struct TYPE * last = TAILQ_LAST(headp, HEADNAME); \
26    TAILQ_REMOVE(headp, last, NAME); \
27})
28#else
29#define MY_TAILQ_REMOVE_LAST(headp, TYPE, HEADNAME, NAME) \
30    TAILQ_REMOVE(headp, TAILQ_LAST(headp, HEADNAME), NAME)
31#endif
32
33int main () {
34
35struct req {
36  int pri, rqr;
37  TAILQ_ENTRY(req) x;
38};
39
40TAILQ_HEAD(reql, req);
41
42struct reql reqs = TAILQ_HEAD_INITIALIZER(reqs);
43TAILQ_INIT(&reqs);
44
45struct req
46  r1 = {1, 42},
47  r2 = {2, 42};
48
49struct req *cur;
50/*
51  (Irrelevant to the bug, not a problem:)
52  You can't navigate next/prev for unlisted elements (it crashes).
53  So I only show them for listed ones.
54*/
55
56printf("r1@%p, r2@%p\n", &r1, &r2);
57
58printf("reqs.first = %p\n", TAILQ_FIRST(&reqs));
59printf("reqs.last = %p\n", TAILQ_LAST(&reqs, reql));
60printf("reqs =");
61TAILQ_FOREACH(cur, &reqs, x)
62    printf(" %p", cur);
63printf("\n");
64
65
66TAILQ_INSERT_TAIL(&reqs, &r1, x);
67
68printf("-\n");
69printf("r1.next=%p\n", TAILQ_NEXT(&r1, x));             // a&e: (nil)   is last
70printf("r1.prev=%p\n", TAILQ_PREV(&r1, reql, x));       // a&e: (nil)   is first
71
72printf("reqs.first = %p\n", TAILQ_FIRST(&reqs));
73printf("reqs.last = %p\n", TAILQ_LAST(&reqs, reql));
74printf("reqs =");
75TAILQ_FOREACH(cur, &reqs, x)
76    printf(" %p", cur);
77printf("\n");
78
79TAILQ_INSERT_TAIL(&reqs, &r2, x);
80
81printf("-\n");
82printf("r1.next=%p\n", TAILQ_NEXT(&r1, x));             // a&e: @r2     has succ
83printf("r1.prev=%p\n", TAILQ_PREV(&r1, reql, x));       // a&e: (nil)   is first
84printf("r2.next=%p\n", TAILQ_NEXT(&r2, x));             // a&e: (nil)   is last
85printf("r2.prev=%p\n", TAILQ_PREV(&r2, reql, x));       // a&e: @r1     has pred
86
87printf("reqs.first = %p\n", TAILQ_FIRST(&reqs));
88printf("reqs.last = %p\n", TAILQ_LAST(&reqs, reql));
89printf("reqs =");
90TAILQ_FOREACH(cur, &reqs, x)
91    printf(" %p", cur);
92printf("\n");
93
94MY_TAILQ_REMOVE_LAST(&reqs, req, reql, x);
95
96printf("-\n");
97printf("r1.next=%p\n", TAILQ_NEXT(&r1, x));             //   e: (nil)   is last;   a: @r2
98printf("r1.prev=%p\n", TAILQ_PREV(&r1, reql, x));       //   e: (nil)   is first;  a: @r2
99
100printf("reqs.first = %p\n", TAILQ_FIRST(&reqs));
101printf("reqs.last = %p\n", TAILQ_LAST(&reqs, reql));
102printf("reqs =");
103TAILQ_FOREACH(cur, &reqs, x)
104    printf(" %p", cur);
105printf("\n");
106
107MY_TAILQ_REMOVE_LAST(&reqs, req, reql, x);
108
109printf("-\n");
110
111printf("reqs.first = %p\n", TAILQ_FIRST(&reqs));
112printf("reqs.last = %p\n", TAILQ_LAST(&reqs, reql));
113printf("reqs =");                                       //   e: (none);  a: @
114TAILQ_FOREACH(cur, &reqs, x)
115    printf(" %p", cur);
116printf("\n");
117
118}
Note: See TracBrowser for help on using the repository browser.