tree:   https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git 
ftrace/core
head:   83dddc0b1e2dd1894186a46acce4dfce75d60c72
commit: 83dddc0b1e2dd1894186a46acce4dfce75d60c72 [46/46] tracing: Rewrite 
filter logic to be simpler and faster

smatch warnings:
kernel/trace/trace_events_filter.c:467 predicate_parse() warn: possible memory 
leak of 'inverts'

# 
https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git/commit/?id=83dddc0b1e2dd1894186a46acce4dfce75d60c72
git remote add trace 
https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
git remote update trace
git checkout 83dddc0b1e2dd1894186a46acce4dfce75d60c72
vim +/inverts +467 kernel/trace/trace_events_filter.c

61e9dea2 Steven Rostedt          2011-01-27  159  
83dddc0b Steven Rostedt (VMware  2018-03-09  160) /*
83dddc0b Steven Rostedt (VMware  2018-03-09  161)  * Without going into a 
formal proof, this explains the method that is used in
83dddc0b Steven Rostedt (VMware  2018-03-09  162)  * parsing the logical 
expressions.
83dddc0b Steven Rostedt (VMware  2018-03-09  163)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  164)  * For example, if we have: 
"a && !(!b || (c && g)) || d || e && !f"
83dddc0b Steven Rostedt (VMware  2018-03-09  165)  * The first pass will 
convert it into the following program:
83dddc0b Steven Rostedt (VMware  2018-03-09  166)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  167)  * n1: r=a;       l1: if (!r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  168)  * n2: r=b;       l2: if (!r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  169)  * n3: r=c; r=!r; l3: if (r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  170)  * n4: r=g; r=!r; l4: if (r) 
goto l5;
83dddc0b Steven Rostedt (VMware  2018-03-09  171)  * n5: r=d;       l5: if (r) 
goto T
83dddc0b Steven Rostedt (VMware  2018-03-09  172)  * n6: r=e;       l6: if (!r) 
goto l7;
83dddc0b Steven Rostedt (VMware  2018-03-09  173)  * n7: r=f; r=!r; l7: if (!r) 
goto F
83dddc0b Steven Rostedt (VMware  2018-03-09  174)  * T: return TRUE
83dddc0b Steven Rostedt (VMware  2018-03-09  175)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  176)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  177)  * To do this, we use a data 
structure to represent each of the above
83dddc0b Steven Rostedt (VMware  2018-03-09  178)  * predicate and conditions 
that has:
83dddc0b Steven Rostedt (VMware  2018-03-09  179)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  180)  *  predicate, 
when_to_branch, invert, target
83dddc0b Steven Rostedt (VMware  2018-03-09  181)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  182)  * The "predicate" will hold 
the function to determine the result "r".
83dddc0b Steven Rostedt (VMware  2018-03-09  183)  * The "when_to_branch" 
denotes what "r" should be if a branch is to be taken
83dddc0b Steven Rostedt (VMware  2018-03-09  184)  * "&&" would contain "!r" or 
(0) and "||" would contain "r" or (1).
83dddc0b Steven Rostedt (VMware  2018-03-09  185)  * The "invert" holds whether 
the value should be reversed before testing.
83dddc0b Steven Rostedt (VMware  2018-03-09  186)  * The "target" contains the 
label "l#" to jump to.
83dddc0b Steven Rostedt (VMware  2018-03-09  187)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  188)  * A stack is created to hold 
values when parentheses are used.
83dddc0b Steven Rostedt (VMware  2018-03-09  189)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  190)  * To simplify the logic, the 
labels will start at 0 and not 1.
83dddc0b Steven Rostedt (VMware  2018-03-09  191)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  192)  * The possible invert values 
are 1 and 0. The number of "!"s that are in scope
83dddc0b Steven Rostedt (VMware  2018-03-09  193)  * before the predicate 
determines the invert value, if the number is odd then
83dddc0b Steven Rostedt (VMware  2018-03-09  194)  * the invert value is 1 and 
0 otherwise. This means the invert value only
83dddc0b Steven Rostedt (VMware  2018-03-09  195)  * needs to be toggled when a 
new "!" is introduced compared to what is stored
83dddc0b Steven Rostedt (VMware  2018-03-09  196)  * on the stack, where 
parentheses were used.
83dddc0b Steven Rostedt (VMware  2018-03-09  197)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  198)  * The top of the stack and 
"invert" are initialized to zero.
83dddc0b Steven Rostedt (VMware  2018-03-09  199)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  200)  * ** FIRST PASS **
83dddc0b Steven Rostedt (VMware  2018-03-09  201)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  202)  * #1 A loop through all the 
tokens is done:
83dddc0b Steven Rostedt (VMware  2018-03-09  203)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  204)  * #2 If the token is an "(", 
the stack is push, and the current stack value
83dddc0b Steven Rostedt (VMware  2018-03-09  205)  *    gets the current invert 
value, and the loop continues to the next token.
83dddc0b Steven Rostedt (VMware  2018-03-09  206)  *    The top of the stack 
saves the "invert" value to keep track of what
83dddc0b Steven Rostedt (VMware  2018-03-09  207)  *    the current inversion 
is. As "!(a && !b || c)" would require all
83dddc0b Steven Rostedt (VMware  2018-03-09  208)  *    predicates being 
affected separately by the "!" before the parentheses.
83dddc0b Steven Rostedt (VMware  2018-03-09  209)  *    And that would end up 
being equivalent to "(!a || b) && !c"
83dddc0b Steven Rostedt (VMware  2018-03-09  210)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  211)  * #3 If the token is an "!", 
the current "invert" value gets inverted, and
83dddc0b Steven Rostedt (VMware  2018-03-09  212)  *    the loop continues. 
Note, if the next token is a predicate, then
83dddc0b Steven Rostedt (VMware  2018-03-09  213)  *    this "invert" value is 
only valid for the current program entry,
83dddc0b Steven Rostedt (VMware  2018-03-09  214)  *    and does not affect 
other predicates later on.
83dddc0b Steven Rostedt (VMware  2018-03-09  215)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  216)  * The only other acceptable 
token is the predicate string.
83dddc0b Steven Rostedt (VMware  2018-03-09  217)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  218)  * #4 A new entry into the 
program is added saving: the predicate and the
83dddc0b Steven Rostedt (VMware  2018-03-09  219)  *    current value of 
"invert". The target is currently assigned to the
83dddc0b Steven Rostedt (VMware  2018-03-09  220)  *    previous program index 
(this will not be its final value).
83dddc0b Steven Rostedt (VMware  2018-03-09  221)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  222)  * #5 We now enter another 
loop and look at the next token. The only valid
83dddc0b Steven Rostedt (VMware  2018-03-09  223)  *    tokens are ")", "&&", 
"||" or end of the input string "\0".
83dddc0b Steven Rostedt (VMware  2018-03-09  224)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  225)  * #6 The invert variable is 
reset to the current value saved on the top of
83dddc0b Steven Rostedt (VMware  2018-03-09  226)  *    the stack.
83dddc0b Steven Rostedt (VMware  2018-03-09  227)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  228)  * #7 The top of the stack 
holds not only the current invert value, but also
83dddc0b Steven Rostedt (VMware  2018-03-09  229)  *    if a "&&" or "||" needs 
to be processed. Note, the "&&" takes higher
83dddc0b Steven Rostedt (VMware  2018-03-09  230)  *    precedence than "||". 
That is "a && b || c && d" is equivalent to
83dddc0b Steven Rostedt (VMware  2018-03-09  231)  *    "(a && b) || (c && d)". 
Thus the first thing to do is to see if "&&" needs
83dddc0b Steven Rostedt (VMware  2018-03-09  232)  *    to be processed. This 
is the case if an "&&" was the last token. If it was
83dddc0b Steven Rostedt (VMware  2018-03-09  233)  *    then we call 
update_preds(). This takes the program, the current index in
83dddc0b Steven Rostedt (VMware  2018-03-09  234)  *    the program, and the 
current value of "invert".  More will be described
83dddc0b Steven Rostedt (VMware  2018-03-09  235)  *    below about this 
function.
83dddc0b Steven Rostedt (VMware  2018-03-09  236)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  237)  * #8 If the next token is 
"&&" then we set a flag in the top of the stack
83dddc0b Steven Rostedt (VMware  2018-03-09  238)  *    that denotes that "&&" 
needs to be processed, break out of this loop
83dddc0b Steven Rostedt (VMware  2018-03-09  239)  *    and continue with the 
outer loop.
83dddc0b Steven Rostedt (VMware  2018-03-09  240)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  241)  * #9 Otherwise, if a "||" 
needs to be processed then update_preds() is called.
83dddc0b Steven Rostedt (VMware  2018-03-09  242)  *    This is called with the 
program, the current index in the program, but
83dddc0b Steven Rostedt (VMware  2018-03-09  243)  *    this time with an 
inverted value of "invert" (that is !invert). This is
83dddc0b Steven Rostedt (VMware  2018-03-09  244)  *    because the value taken 
will become the "when_to_branch" value of the
83dddc0b Steven Rostedt (VMware  2018-03-09  245)  *    program.
83dddc0b Steven Rostedt (VMware  2018-03-09  246)  *    Note, this is called 
when the next token is not an "&&". As stated before,
83dddc0b Steven Rostedt (VMware  2018-03-09  247)  *    "&&" takes higher 
precedence, and "||" should not be processed yet if the
83dddc0b Steven Rostedt (VMware  2018-03-09  248)  *    next logical operation 
is "&&".
83dddc0b Steven Rostedt (VMware  2018-03-09  249)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  250)  * #10 If the next token is 
"||" then we set a flag in the top of the stack
83dddc0b Steven Rostedt (VMware  2018-03-09  251)  *     that denotes that "||" 
needs to be processed, break out of this loop
83dddc0b Steven Rostedt (VMware  2018-03-09  252)  *     and continue with the 
outer loop.
83dddc0b Steven Rostedt (VMware  2018-03-09  253)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  254)  * #11 If this is the end of 
the input string "\0" then we break out of both
83dddc0b Steven Rostedt (VMware  2018-03-09  255)  *     loops.
83dddc0b Steven Rostedt (VMware  2018-03-09  256)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  257)  * #12 Otherwise, the next 
token is ")", where we pop the stack and continue
83dddc0b Steven Rostedt (VMware  2018-03-09  258)  *     this inner loop.
83dddc0b Steven Rostedt (VMware  2018-03-09  259)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  260)  * Now to discuss the 
update_pred() function, as that is key to the setting up
83dddc0b Steven Rostedt (VMware  2018-03-09  261)  * of the program. Remember 
the "target" of the program is initialized to the
83dddc0b Steven Rostedt (VMware  2018-03-09  262)  * previous index and not the 
"l" label. The target holds the index into the
83dddc0b Steven Rostedt (VMware  2018-03-09  263)  * program that gets affected 
by the operand. Thus if we have something like
83dddc0b Steven Rostedt (VMware  2018-03-09  264)  *  "a || b && c", when we 
process "a" the target will be "-1" (undefined).
83dddc0b Steven Rostedt (VMware  2018-03-09  265)  * When we process "b", its 
target is "0", which is the index of "a", as that's
83dddc0b Steven Rostedt (VMware  2018-03-09  266)  * the predicate that is 
affected by "||". But because the next token after "b"
83dddc0b Steven Rostedt (VMware  2018-03-09  267)  * is "&&" we don't call 
update_preds(). Instead continue to "c". As the
83dddc0b Steven Rostedt (VMware  2018-03-09  268)  * next token after "c" is 
not "&&" but the end of input, we first process the
83dddc0b Steven Rostedt (VMware  2018-03-09  269)  * "&&" by calling 
update_preds() for the "&&" then we process the "||" by
83dddc0b Steven Rostedt (VMware  2018-03-09  270)  * callin updates_preds() 
with the values for processing "||".
83dddc0b Steven Rostedt (VMware  2018-03-09  271)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  272)  * What does that mean? What 
update_preds() does is to first save the "target"
83dddc0b Steven Rostedt (VMware  2018-03-09  273)  * of the program entry 
indexed by the current program entry's "target"
83dddc0b Steven Rostedt (VMware  2018-03-09  274)  * (remember the "target" is 
initialized to previous program entry), and then
83dddc0b Steven Rostedt (VMware  2018-03-09  275)  * sets that "target" to the 
current index which represents the label "l#".
83dddc0b Steven Rostedt (VMware  2018-03-09  276)  * That entry's 
"when_to_branch" is set to the value passed in (the "invert"
83dddc0b Steven Rostedt (VMware  2018-03-09  277)  * or "!invert"). Then it 
sets the current program entry's target to the saved
83dddc0b Steven Rostedt (VMware  2018-03-09  278)  * "target" value (the old 
value of the program that had its "target" updated
83dddc0b Steven Rostedt (VMware  2018-03-09  279)  * to the label).
83dddc0b Steven Rostedt (VMware  2018-03-09  280)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  281)  * Looking back at "a || b && 
c", we have the following steps:
83dddc0b Steven Rostedt (VMware  2018-03-09  282)  *  "a"  - prog[0] = { "a", 
X, -1 } // pred, when_to_branch, target
83dddc0b Steven Rostedt (VMware  2018-03-09  283)  *  "||" - flag that we need 
to process "||"; continue outer loop
83dddc0b Steven Rostedt (VMware  2018-03-09  284)  *  "b"  - prog[1] = { "b", 
X, 0 }
83dddc0b Steven Rostedt (VMware  2018-03-09  285)  *  "&&" - flag that we need 
to process "&&"; continue outer loop
83dddc0b Steven Rostedt (VMware  2018-03-09  286)  * (Notice we did not process 
"||")
83dddc0b Steven Rostedt (VMware  2018-03-09  287)  *  "c"  - prog[2] = { "c", 
X, 1 }
83dddc0b Steven Rostedt (VMware  2018-03-09  288)  *  update_preds(prog, 2, 0); 
// invert = 0 as we are processing "&&"
83dddc0b Steven Rostedt (VMware  2018-03-09  289)  *    t = prog[2].target; // 
t = 1
83dddc0b Steven Rostedt (VMware  2018-03-09  290)  *    s = prog[t].target; // 
s = 0
83dddc0b Steven Rostedt (VMware  2018-03-09  291)  *    prog[t].target = 2; // 
Set target to "l2"
83dddc0b Steven Rostedt (VMware  2018-03-09  292)  *    prog[t].when_to_branch 
= 0;
83dddc0b Steven Rostedt (VMware  2018-03-09  293)  *    prog[2].target = s;
83dddc0b Steven Rostedt (VMware  2018-03-09  294)  * update_preds(prog, 2, 1); 
// invert = 1 as we are now processing "||"
83dddc0b Steven Rostedt (VMware  2018-03-09  295)  *    t = prog[2].target; // 
t = 0
83dddc0b Steven Rostedt (VMware  2018-03-09  296)  *    s = prog[t].target; // 
s = -1
83dddc0b Steven Rostedt (VMware  2018-03-09  297)  *    prog[t].target = 2; // 
Set target to "l2"
83dddc0b Steven Rostedt (VMware  2018-03-09  298)  *    prog[t].when_to_branch 
= 1;
83dddc0b Steven Rostedt (VMware  2018-03-09  299)  *    prog[2].target = s;
83dddc0b Steven Rostedt (VMware  2018-03-09  300)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  301)  * #13 Which brings us to the 
final step of the first pass, which is to set
83dddc0b Steven Rostedt (VMware  2018-03-09  302)  *     the last program 
entry's when_to_branch and target, which will be
83dddc0b Steven Rostedt (VMware  2018-03-09  303)  *     when_to_branch = 0; 
target = N; ( the label after the program entry after
83dddc0b Steven Rostedt (VMware  2018-03-09  304)  *     the last program entry 
processed above).
83dddc0b Steven Rostedt (VMware  2018-03-09  305)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  306)  * If we denote "TRUE" to be 
the entry after the last program entry processed,
83dddc0b Steven Rostedt (VMware  2018-03-09  307)  * and "FALSE" the program 
entry after that, we are now done with the first
83dddc0b Steven Rostedt (VMware  2018-03-09  308)  * pass.
83dddc0b Steven Rostedt (VMware  2018-03-09  309)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  310)  * Making the above "a || b 
&& c" have a progam of:
83dddc0b Steven Rostedt (VMware  2018-03-09  311)  *  prog[0] = { "a", 1, 2 }
83dddc0b Steven Rostedt (VMware  2018-03-09  312)  *  prog[1] = { "b", 0, 2 }
83dddc0b Steven Rostedt (VMware  2018-03-09  313)  *  prog[2] = { "c", 0, 3 }
83dddc0b Steven Rostedt (VMware  2018-03-09  314)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  315)  * Which translates into:
83dddc0b Steven Rostedt (VMware  2018-03-09  316)  * n0: r = a; l0: if (r) goto 
l2;
83dddc0b Steven Rostedt (VMware  2018-03-09  317)  * n1: r = b; l1: if (!r) 
goto l2;
83dddc0b Steven Rostedt (VMware  2018-03-09  318)  * n2: r = c; l2: if (!r) 
goto l3;  // Which is the same as "goto F;"
83dddc0b Steven Rostedt (VMware  2018-03-09  319)  * T: return TRUE; l3:
83dddc0b Steven Rostedt (VMware  2018-03-09  320)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  321)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  322)  * Although, after the first 
pass, the program is correct, it is
83dddc0b Steven Rostedt (VMware  2018-03-09  323)  * inefficient. The simple 
sample of "a || b && c" could be easily been
83dddc0b Steven Rostedt (VMware  2018-03-09  324)  * converted into:
83dddc0b Steven Rostedt (VMware  2018-03-09  325)  * n0: r = a; if (r) goto T
83dddc0b Steven Rostedt (VMware  2018-03-09  326)  * n1: r = b; if (!r) goto F
83dddc0b Steven Rostedt (VMware  2018-03-09  327)  * n2: r = c; if (!r) goto F
83dddc0b Steven Rostedt (VMware  2018-03-09  328)  * T: return TRUE;
83dddc0b Steven Rostedt (VMware  2018-03-09  329)  * F: return FALSE;
83dddc0b Steven Rostedt (VMware  2018-03-09  330)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  331)  * The First Pass is over the 
input string. The next too passes are over
83dddc0b Steven Rostedt (VMware  2018-03-09  332)  * the program itself.
83dddc0b Steven Rostedt (VMware  2018-03-09  333)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  334)  * ** SECOND PASS **
83dddc0b Steven Rostedt (VMware  2018-03-09  335)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  336)  * Which brings us to the 
second pass. If a jump to a label has the
83dddc0b Steven Rostedt (VMware  2018-03-09  337)  * same condition as that 
label, it can instead jump to its target.
83dddc0b Steven Rostedt (VMware  2018-03-09  338)  * The original example of "a 
&& !(!b || (c && g)) || d || e && !f"
83dddc0b Steven Rostedt (VMware  2018-03-09  339)  * where the first pass gives 
us:
83dddc0b Steven Rostedt (VMware  2018-03-09  340)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  341)  * n1: r=a;       l1: if (!r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  342)  * n2: r=b;       l2: if (!r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  343)  * n3: r=c; r=!r; l3: if (r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  344)  * n4: r=g; r=!r; l4: if (r) 
goto l5;
83dddc0b Steven Rostedt (VMware  2018-03-09  345)  * n5: r=d;       l5: if (r) 
goto T
83dddc0b Steven Rostedt (VMware  2018-03-09  346)  * n6: r=e;       l6: if (!r) 
goto l7;
83dddc0b Steven Rostedt (VMware  2018-03-09  347)  * n7: r=f; r=!r; l7: if (!r) 
goto F:
83dddc0b Steven Rostedt (VMware  2018-03-09  348)  * T: return TRUE;
83dddc0b Steven Rostedt (VMware  2018-03-09  349)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  350)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  351)  * We can see that "l3: if 
(r) goto l4;" and at l4, we have "if (r) goto l5;".
83dddc0b Steven Rostedt (VMware  2018-03-09  352)  * And "l5: if (r) goto T", 
we could optimize this by converting l3 and l4
83dddc0b Steven Rostedt (VMware  2018-03-09  353)  * to go directly to T. To 
accomplish this, we start from the last
83dddc0b Steven Rostedt (VMware  2018-03-09  354)  * entry in the program and 
work our way back. If the target of the entry
83dddc0b Steven Rostedt (VMware  2018-03-09  355)  * has the same 
"when_to_branch" then we could use that entry's target.
83dddc0b Steven Rostedt (VMware  2018-03-09  356)  * Doing this, the above 
would end up as:
83dddc0b Steven Rostedt (VMware  2018-03-09  357)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  358)  * n1: r=a;       l1: if (!r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  359)  * n2: r=b;       l2: if (!r) 
goto l4;
83dddc0b Steven Rostedt (VMware  2018-03-09  360)  * n3: r=c; r=!r; l3: if (r) 
goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  361)  * n4: r=g; r=!r; l4: if (r) 
goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  362)  * n5: r=d;       l5: if (r) 
goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  363)  * n6: r=e;       l6: if (!r) 
goto F;
83dddc0b Steven Rostedt (VMware  2018-03-09  364)  * n7: r=f; r=!r; l7: if (!r) 
goto F;
83dddc0b Steven Rostedt (VMware  2018-03-09  365)  * T: return TRUE
83dddc0b Steven Rostedt (VMware  2018-03-09  366)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  367)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  368)  * In that same pass, if the 
"when_to_branch" doesn't match, we can simply
83dddc0b Steven Rostedt (VMware  2018-03-09  369)  * go to the program entry 
after the label. That is, "l2: if (!r) goto l4;"
83dddc0b Steven Rostedt (VMware  2018-03-09  370)  * where "l4: if (r) goto 
T;", then we can convert l2 to be:
83dddc0b Steven Rostedt (VMware  2018-03-09  371)  * "l2: if (!r) goto n5;".
83dddc0b Steven Rostedt (VMware  2018-03-09  372)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  373)  * This will have the second 
pass give us:
83dddc0b Steven Rostedt (VMware  2018-03-09  374)  * n1: r=a;       l1: if (!r) 
goto n5;
83dddc0b Steven Rostedt (VMware  2018-03-09  375)  * n2: r=b;       l2: if (!r) 
goto n5;
83dddc0b Steven Rostedt (VMware  2018-03-09  376)  * n3: r=c; r=!r; l3: if (r) 
goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  377)  * n4: r=g; r=!r; l4: if (r) 
goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  378)  * n5: r=d;       l5: if (r) 
goto T
83dddc0b Steven Rostedt (VMware  2018-03-09  379)  * n6: r=e;       l6: if (!r) 
goto F;
83dddc0b Steven Rostedt (VMware  2018-03-09  380)  * n7: r=f; r=!r; l7: if (!r) 
goto F
83dddc0b Steven Rostedt (VMware  2018-03-09  381)  * T: return TRUE
83dddc0b Steven Rostedt (VMware  2018-03-09  382)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  383)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  384)  * Notice, all the "l#" 
labels are no longer used, and they can now
83dddc0b Steven Rostedt (VMware  2018-03-09  385)  * be discarded.
83dddc0b Steven Rostedt (VMware  2018-03-09  386)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  387)  * ** THIRD PASS **
83dddc0b Steven Rostedt (VMware  2018-03-09  388)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  389)  * For the third pass we deal 
with the inverts. As they simply just
83dddc0b Steven Rostedt (VMware  2018-03-09  390)  * make the "when_to_branch" 
get inverted, a simple loop over the
83dddc0b Steven Rostedt (VMware  2018-03-09  391)  * program to that does: 
"when_to_branch ^= invert;" will do the
83dddc0b Steven Rostedt (VMware  2018-03-09  392)  * job, leaving us with:
83dddc0b Steven Rostedt (VMware  2018-03-09  393)  * n1: r=a; if (!r) goto n5;
83dddc0b Steven Rostedt (VMware  2018-03-09  394)  * n2: r=b; if (!r) goto n5;
83dddc0b Steven Rostedt (VMware  2018-03-09  395)  * n3: r=c: if (!r) goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  396)  * n4: r=g; if (!r) goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  397)  * n5: r=d; if (r) goto T
83dddc0b Steven Rostedt (VMware  2018-03-09  398)  * n6: r=e; if (!r) goto F;
83dddc0b Steven Rostedt (VMware  2018-03-09  399)  * n7: r=f; if (r) goto F
83dddc0b Steven Rostedt (VMware  2018-03-09  400)  * T: return TRUE
83dddc0b Steven Rostedt (VMware  2018-03-09  401)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  402)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  403)  * As "r = a; if (!r) goto 
n5;" is obviously the same as
83dddc0b Steven Rostedt (VMware  2018-03-09  404)  * "if (!a) goto n5;" without 
doing anything we can interperate the
83dddc0b Steven Rostedt (VMware  2018-03-09  405)  * program as:
83dddc0b Steven Rostedt (VMware  2018-03-09  406)  * n1: if (!a) goto n5;
83dddc0b Steven Rostedt (VMware  2018-03-09  407)  * n2: if (!b) goto n5;
83dddc0b Steven Rostedt (VMware  2018-03-09  408)  * n3: if (!c) goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  409)  * n4: if (!g) goto T;
83dddc0b Steven Rostedt (VMware  2018-03-09  410)  * n5: if (d) goto T
83dddc0b Steven Rostedt (VMware  2018-03-09  411)  * n6: if (!e) goto F;
83dddc0b Steven Rostedt (VMware  2018-03-09  412)  * n7: if (f) goto F
83dddc0b Steven Rostedt (VMware  2018-03-09  413)  * T: return TRUE
83dddc0b Steven Rostedt (VMware  2018-03-09  414)  * F: return FALSE
83dddc0b Steven Rostedt (VMware  2018-03-09  415)  *
83dddc0b Steven Rostedt (VMware  2018-03-09  416)  * Since the inverts are 
discarded at the end, there's no reason to store
83dddc0b Steven Rostedt (VMware  2018-03-09  417)  * them in the program array 
(and waste memory). A separate array to hold
83dddc0b Steven Rostedt (VMware  2018-03-09  418)  * the inverts is used and 
freed at the end.
83dddc0b Steven Rostedt (VMware  2018-03-09  419)  */
83dddc0b Steven Rostedt (VMware  2018-03-09  420) static struct prog_entry *
83dddc0b Steven Rostedt (VMware  2018-03-09  421) predicate_parse(const char 
*str, int nr_parens, int nr_preds,
83dddc0b Steven Rostedt (VMware  2018-03-09  422)               parse_pred_fn 
parse_pred, void *data,
83dddc0b Steven Rostedt (VMware  2018-03-09  423)               struct 
filter_parse_error *pe)
83dddc0b Steven Rostedt (VMware  2018-03-09  424) {
83dddc0b Steven Rostedt (VMware  2018-03-09  425)       struct prog_entry 
*prog_stack;
83dddc0b Steven Rostedt (VMware  2018-03-09  426)       struct prog_entry *prog;
83dddc0b Steven Rostedt (VMware  2018-03-09  427)       const char *ptr = str;
83dddc0b Steven Rostedt (VMware  2018-03-09  428)       char *inverts = NULL;
83dddc0b Steven Rostedt (VMware  2018-03-09  429)       int *op_stack;
83dddc0b Steven Rostedt (VMware  2018-03-09  430)       int *top;
83dddc0b Steven Rostedt (VMware  2018-03-09  431)       int invert = 0;
83dddc0b Steven Rostedt (VMware  2018-03-09  432)       int ret = -ENOMEM;
83dddc0b Steven Rostedt (VMware  2018-03-09  433)       int len;
83dddc0b Steven Rostedt (VMware  2018-03-09  434)       int N = 0;
83dddc0b Steven Rostedt (VMware  2018-03-09  435)       int i;
83dddc0b Steven Rostedt (VMware  2018-03-09  436) 
83dddc0b Steven Rostedt (VMware  2018-03-09  437)       nr_preds += 2; /* For 
TRUE and FALSE */
83dddc0b Steven Rostedt (VMware  2018-03-09  438) 
83dddc0b Steven Rostedt (VMware  2018-03-09  439)       op_stack = 
kmalloc(sizeof(*op_stack) * nr_parens, GFP_KERNEL);
83dddc0b Steven Rostedt (VMware  2018-03-09  440)       if (!op_stack)
83dddc0b Steven Rostedt (VMware  2018-03-09  441)               return 
ERR_PTR(-ENOMEM);
83dddc0b Steven Rostedt (VMware  2018-03-09  442)       prog_stack = 
kmalloc(sizeof(*prog_stack) * nr_preds, GFP_KERNEL);
83dddc0b Steven Rostedt (VMware  2018-03-09  443)       if (!prog_stack) {
83dddc0b Steven Rostedt (VMware  2018-03-09  444)               parse_error(pe, 
-ENOMEM, 0);
83dddc0b Steven Rostedt (VMware  2018-03-09  445)               goto out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  446)       }
83dddc0b Steven Rostedt (VMware  2018-03-09  447)       inverts = 
kmalloc(sizeof(*inverts) * nr_preds, GFP_KERNEL);
83dddc0b Steven Rostedt (VMware  2018-03-09  448)       if (!inverts) {
83dddc0b Steven Rostedt (VMware  2018-03-09  449)               parse_error(pe, 
-ENOMEM, 0);
83dddc0b Steven Rostedt (VMware  2018-03-09  450)               goto out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  451)       }
83dddc0b Steven Rostedt (VMware  2018-03-09  452) 
83dddc0b Steven Rostedt (VMware  2018-03-09  453)       top = op_stack;
83dddc0b Steven Rostedt (VMware  2018-03-09  454)       prog = prog_stack;
83dddc0b Steven Rostedt (VMware  2018-03-09  455)       *top = 0;
83dddc0b Steven Rostedt (VMware  2018-03-09  456) 
83dddc0b Steven Rostedt (VMware  2018-03-09  457)       /* First pass */
83dddc0b Steven Rostedt (VMware  2018-03-09  458)       while (*ptr) {          
                                /* #1 */
83dddc0b Steven Rostedt (VMware  2018-03-09  459)               const char 
*next = ptr++;
83dddc0b Steven Rostedt (VMware  2018-03-09  460) 
83dddc0b Steven Rostedt (VMware  2018-03-09  461)               if 
(isspace(*next))
83dddc0b Steven Rostedt (VMware  2018-03-09  462)                       
continue;
83dddc0b Steven Rostedt (VMware  2018-03-09  463) 
83dddc0b Steven Rostedt (VMware  2018-03-09  464)               switch (*next) {
83dddc0b Steven Rostedt (VMware  2018-03-09  465)               case '(':       
                                /* #2 */
83dddc0b Steven Rostedt (VMware  2018-03-09  466)                       if (top 
- op_stack > nr_parens)
83dddc0b Steven Rostedt (VMware  2018-03-09 @467)                               
return ERR_PTR(-EINVAL);
                                                                                
       ^^^^^^^^^^^^^^^^
goto out_free;

83dddc0b Steven Rostedt (VMware  2018-03-09  468)                       
*(++top) = invert;
83dddc0b Steven Rostedt (VMware  2018-03-09  469)                       
continue;
83dddc0b Steven Rostedt (VMware  2018-03-09  470)               case '!':       
                                /* #3 */
83dddc0b Steven Rostedt (VMware  2018-03-09  471)                       if 
(!is_not(next))
83dddc0b Steven Rostedt (VMware  2018-03-09  472)                               
break;
83dddc0b Steven Rostedt (VMware  2018-03-09  473)                       invert 
= !invert;
83dddc0b Steven Rostedt (VMware  2018-03-09  474)                       
continue;
83dddc0b Steven Rostedt (VMware  2018-03-09  475)               }
83dddc0b Steven Rostedt (VMware  2018-03-09  476) 
83dddc0b Steven Rostedt (VMware  2018-03-09  477)               if (N >= 
nr_preds) {
83dddc0b Steven Rostedt (VMware  2018-03-09  478)                       
parse_error(pe, FILT_ERR_TOO_MANY_PREDS, next - str);
83dddc0b Steven Rostedt (VMware  2018-03-09  479)                       goto 
out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  480)               }
83dddc0b Steven Rostedt (VMware  2018-03-09  481) 
83dddc0b Steven Rostedt (VMware  2018-03-09  482)               inverts[N] = 
invert;                            /* #4 */
83dddc0b Steven Rostedt (VMware  2018-03-09  483)               prog[N].target 
= N-1;
83dddc0b Steven Rostedt (VMware  2018-03-09  484) 
83dddc0b Steven Rostedt (VMware  2018-03-09  485)               len = 
parse_pred(next, data, ptr - str, pe, &prog[N].pred);
83dddc0b Steven Rostedt (VMware  2018-03-09  486)               if (len < 0) {
83dddc0b Steven Rostedt (VMware  2018-03-09  487)                       ret = 
len;
83dddc0b Steven Rostedt (VMware  2018-03-09  488)                       goto 
out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  489)               }
83dddc0b Steven Rostedt (VMware  2018-03-09  490)               ptr = next + 
len;
83dddc0b Steven Rostedt (VMware  2018-03-09  491) 
83dddc0b Steven Rostedt (VMware  2018-03-09  492)               N++;
83dddc0b Steven Rostedt (VMware  2018-03-09  493) 
83dddc0b Steven Rostedt (VMware  2018-03-09  494)               ret = -1;
83dddc0b Steven Rostedt (VMware  2018-03-09  495)               while (1) {     
                                /* #5 */
83dddc0b Steven Rostedt (VMware  2018-03-09  496)                       next = 
ptr++;
83dddc0b Steven Rostedt (VMware  2018-03-09  497)                       if 
(isspace(*next))
83dddc0b Steven Rostedt (VMware  2018-03-09  498)                               
continue;
83dddc0b Steven Rostedt (VMware  2018-03-09  499) 
83dddc0b Steven Rostedt (VMware  2018-03-09  500)                       switch 
(*next) {
83dddc0b Steven Rostedt (VMware  2018-03-09  501)                       case 
')':
83dddc0b Steven Rostedt (VMware  2018-03-09  502)                       case 
'\0':
83dddc0b Steven Rostedt (VMware  2018-03-09  503)                               
break;
83dddc0b Steven Rostedt (VMware  2018-03-09  504)                       case 
'&':
83dddc0b Steven Rostedt (VMware  2018-03-09  505)                       case 
'|':
83dddc0b Steven Rostedt (VMware  2018-03-09  506)                               
if (next[1] == next[0]) {
83dddc0b Steven Rostedt (VMware  2018-03-09  507)                               
        ptr++;
83dddc0b Steven Rostedt (VMware  2018-03-09  508)                               
        break;
83dddc0b Steven Rostedt (VMware  2018-03-09  509)                               
}
83dddc0b Steven Rostedt (VMware  2018-03-09  510)                       default:
83dddc0b Steven Rostedt (VMware  2018-03-09  511)                               
parse_error(pe, FILT_ERR_TOO_MANY_PREDS,
83dddc0b Steven Rostedt (VMware  2018-03-09  512)                               
            next - str);
83dddc0b Steven Rostedt (VMware  2018-03-09  513)                               
goto out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  514)                       }
83dddc0b Steven Rostedt (VMware  2018-03-09  515) 
83dddc0b Steven Rostedt (VMware  2018-03-09  516)                       invert 
= *top & INVERT;
83dddc0b Steven Rostedt (VMware  2018-03-09  517) 
83dddc0b Steven Rostedt (VMware  2018-03-09  518)                       if 
(*top & PROCESS_AND) {               /* #7 */
83dddc0b Steven Rostedt (VMware  2018-03-09  519)                               
update_preds(prog, N - 1, invert);
83dddc0b Steven Rostedt (VMware  2018-03-09  520)                               
*top &= ~PROCESS_AND;
83dddc0b Steven Rostedt (VMware  2018-03-09  521)                       }
83dddc0b Steven Rostedt (VMware  2018-03-09  522)                       if 
(*next == '&') {                     /* #8 */
83dddc0b Steven Rostedt (VMware  2018-03-09  523)                               
*top |= PROCESS_AND;
83dddc0b Steven Rostedt (VMware  2018-03-09  524)                               
break;
83dddc0b Steven Rostedt (VMware  2018-03-09  525)                       }
83dddc0b Steven Rostedt (VMware  2018-03-09  526)                       if 
(*top & PROCESS_OR) {                /* #9 */
83dddc0b Steven Rostedt (VMware  2018-03-09  527)                               
update_preds(prog, N - 1, !invert);
83dddc0b Steven Rostedt (VMware  2018-03-09  528)                               
*top &= ~PROCESS_OR;
83dddc0b Steven Rostedt (VMware  2018-03-09  529)                       }
83dddc0b Steven Rostedt (VMware  2018-03-09  530)                       if 
(*next == '|') {                     /* #10 */
83dddc0b Steven Rostedt (VMware  2018-03-09  531)                               
*top |= PROCESS_OR;
83dddc0b Steven Rostedt (VMware  2018-03-09  532)                               
break;
83dddc0b Steven Rostedt (VMware  2018-03-09  533)                       }
83dddc0b Steven Rostedt (VMware  2018-03-09  534)                       if 
(!*next)                             /* #11 */
83dddc0b Steven Rostedt (VMware  2018-03-09  535)                               
goto out;
83dddc0b Steven Rostedt (VMware  2018-03-09  536) 
83dddc0b Steven Rostedt (VMware  2018-03-09  537)                       if (top 
== op_stack) {
83dddc0b Steven Rostedt (VMware  2018-03-09  538)                               
ret = -1;
83dddc0b Steven Rostedt (VMware  2018-03-09  539)                               
/* Too few '(' */
83dddc0b Steven Rostedt (VMware  2018-03-09  540)                               
parse_error(pe, FILT_ERR_TOO_MANY_CLOSE, ptr - str);
83dddc0b Steven Rostedt (VMware  2018-03-09  541)                               
goto out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  542)                       }
83dddc0b Steven Rostedt (VMware  2018-03-09  543)                       top--;  
                                /* #12 */
83dddc0b Steven Rostedt (VMware  2018-03-09  544)               }
83dddc0b Steven Rostedt (VMware  2018-03-09  545)       }
83dddc0b Steven Rostedt (VMware  2018-03-09  546)  out:
83dddc0b Steven Rostedt (VMware  2018-03-09  547)       if (top != op_stack) {
83dddc0b Steven Rostedt (VMware  2018-03-09  548)               /* Too many '(' 
*/
83dddc0b Steven Rostedt (VMware  2018-03-09  549)               parse_error(pe, 
FILT_ERR_TOO_MANY_OPEN, ptr - str);
83dddc0b Steven Rostedt (VMware  2018-03-09  550)               goto out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  551)       }
83dddc0b Steven Rostedt (VMware  2018-03-09  552) 
83dddc0b Steven Rostedt (VMware  2018-03-09  553)       prog[N].pred = NULL;    
                                /* #13 */
83dddc0b Steven Rostedt (VMware  2018-03-09  554)       prog[N].target = 1;     
        /* TRUE */
83dddc0b Steven Rostedt (VMware  2018-03-09  555)       prog[N+1].pred = NULL;
83dddc0b Steven Rostedt (VMware  2018-03-09  556)       prog[N+1].target = 0;   
        /* FALSE */
83dddc0b Steven Rostedt (VMware  2018-03-09  557)       prog[N-1].target = N;
83dddc0b Steven Rostedt (VMware  2018-03-09  558)       
prog[N-1].when_to_branch = false;
83dddc0b Steven Rostedt (VMware  2018-03-09  559) 
83dddc0b Steven Rostedt (VMware  2018-03-09  560)       /* Second Pass */
83dddc0b Steven Rostedt (VMware  2018-03-09  561)       for (i = N-1 ; i--; ) {
83dddc0b Steven Rostedt (VMware  2018-03-09  562)               int target = 
prog[i].target;
83dddc0b Steven Rostedt (VMware  2018-03-09  563)               if 
(prog[i].when_to_branch == prog[target].when_to_branch)
83dddc0b Steven Rostedt (VMware  2018-03-09  564)                       
prog[i].target = prog[target].target;
83dddc0b Steven Rostedt (VMware  2018-03-09  565)       }
83dddc0b Steven Rostedt (VMware  2018-03-09  566) 
83dddc0b Steven Rostedt (VMware  2018-03-09  567)       /* Third Pass */
83dddc0b Steven Rostedt (VMware  2018-03-09  568)       for (i = 0; i < N; i++) 
{
83dddc0b Steven Rostedt (VMware  2018-03-09  569)               invert = 
inverts[i] ^ prog[i].when_to_branch;
83dddc0b Steven Rostedt (VMware  2018-03-09  570)               
prog[i].when_to_branch = invert;
83dddc0b Steven Rostedt (VMware  2018-03-09  571)               /* Make sure 
the program always moves forward */
83dddc0b Steven Rostedt (VMware  2018-03-09  572)               if 
(WARN_ON(prog[i].target <= i)) {
83dddc0b Steven Rostedt (VMware  2018-03-09  573)                       ret = 
-EINVAL;
83dddc0b Steven Rostedt (VMware  2018-03-09  574)                       goto 
out_free;
83dddc0b Steven Rostedt (VMware  2018-03-09  575)               }
83dddc0b Steven Rostedt (VMware  2018-03-09  576)       }
83dddc0b Steven Rostedt (VMware  2018-03-09  577) 
83dddc0b Steven Rostedt (VMware  2018-03-09  578)       return prog;
83dddc0b Steven Rostedt (VMware  2018-03-09  579) out_free:
83dddc0b Steven Rostedt (VMware  2018-03-09  580)       kfree(op_stack);
83dddc0b Steven Rostedt (VMware  2018-03-09  581)       kfree(prog_stack);
83dddc0b Steven Rostedt (VMware  2018-03-09  582)       kfree(inverts);
83dddc0b Steven Rostedt (VMware  2018-03-09  583)       return ERR_PTR(ret);
83dddc0b Steven Rostedt (VMware  2018-03-09  584) }
83dddc0b Steven Rostedt (VMware  2018-03-09  585) 

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
_______________________________________________
kbuild mailing list
kbuild@lists.01.org
https://lists.01.org/mailman/listinfo/kbuild

Reply via email to