Every time we set ->report, we also set ->slow_path. This complication is
not necessary. Instead we can change start_report() to check both flags.
This is free, gcc is good enough. This code

        void test_func(struct utrace *utrace)
        {
                if (utrace->slow_path || utrace->report)
                        do_something();
        }

is compiled to

        test_func:
                pushq   %rbp
                testb   $-126, 96(%rdi),
                movq    %rsp, %rbp,
                jne     .L449,
                leave
                ret
        .L449:
                call    do_something
                leave
                ret

Perhaps it makes sense to rename ->slow_path, with it only means
that splice_attaching() is needed and nothing more.

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---

 kernel/utrace.c |   15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

--- __UTRACE/kernel/utrace.c~6_DONT_ABUSE_SLOW_WORK     2009-09-06 
18:07:14.000000000 +0200
+++ __UTRACE/kernel/utrace.c    2009-09-06 18:15:39.000000000 +0200
@@ -644,7 +644,7 @@ static bool utrace_do_stop(struct task_s
                }
                spin_unlock_irq(&target->sighand->siglock);
        } else if (!utrace->report && !utrace->interrupt) {
-               utrace->report = utrace->slow_path = 1;
+               utrace->report = 1;
                set_notify_resume(target);
        }
 
@@ -773,7 +773,7 @@ relock:
                /*
                 * Ensure a reporting pass when we're resumed.
                 */
-               utrace->report = utrace->slow_path = 1;
+               utrace->report = 1;
                set_thread_flag(TIF_NOTIFY_RESUME);
        }
 
@@ -1096,7 +1096,7 @@ int utrace_control(struct task_struct *t
                 */
                clear_engine_wants_stop(engine);
                if (!utrace->report && !utrace->interrupt) {
-                       utrace->report = utrace->slow_path = 1;
+                       utrace->report = 1;
                        set_notify_resume(target);
                }
                break;
@@ -1266,14 +1266,13 @@ struct utrace_report {
 
 /*
  * We are now making the report, so clear the flag saying we need one.
- * When ->report is set, ->slow_path is always set too.  When there is a
- * new attach, ->slow_path is set even without ->report, just so we will
- * know to do splice_attaching() here before the callback loop.
+ * When there is a new attach, ->slow_path is set without ->report, just
+ * so we will know to do splice_attaching() here before the callback loop.
  */
 static void start_report(struct utrace *utrace)
 {
        BUG_ON(utrace->stopped);
-       if (utrace->slow_path) {
+       if (utrace->report || utrace->slow_path) {
                spin_lock(&utrace->lock);
                splice_attaching(utrace);
                utrace->report = 0;
@@ -1310,7 +1309,7 @@ static void finish_report(struct utrace_
                        utrace->interrupt = 1;
                        set_tsk_thread_flag(task, TIF_SIGPENDING);
                } else {
-                       utrace->report = utrace->slow_path = 1;
+                       utrace->report = 1;
                        set_tsk_thread_flag(task, TIF_NOTIFY_RESUME);
                }
                spin_unlock(&utrace->lock);

Reply via email to