I still need to review (and understand ;) the ->reporting logic/barriers
and continue the related discussion.

But can't we move ->reporting from utrace to engine? This saves a word
in task_struct. Yes, this adds the same word to engine, but we should
optimize the common untraced case.

Or do you have other plans for utrace->reporting?

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

 include/linux/utrace_struct.h |    2 --
 include/linux/utrace.h        |    1 +
 kernel/utrace.c               |   38 +++++++++++++++++++-------------------
 3 files changed, 20 insertions(+), 21 deletions(-)

--- __UTRACE/include/linux/utrace_struct.h~1_MV_REPORTING       2009-09-08 
18:15:38.000000000 +0200
+++ __UTRACE/include/linux/utrace_struct.h      2009-09-12 02:07:30.000000000 
+0200
@@ -30,8 +30,6 @@ struct utrace {
        struct list_head attached, attaching;
        spinlock_t lock;
 
-       struct utrace_engine *reporting;
-
        unsigned int stopped:1;
        unsigned int report:1;
        unsigned int interrupt:1;
--- __UTRACE/include/linux/utrace.h~1_MV_REPORTING      2009-09-12 
02:02:45.000000000 +0200
+++ __UTRACE/include/linux/utrace.h     2009-09-12 02:09:37.000000000 +0200
@@ -327,6 +327,7 @@ struct utrace_engine {
 
 /* public: */
        const struct utrace_engine_ops *ops;
+       bool reporting;
        void *data;
 
        unsigned long flags;
--- __UTRACE/kernel/utrace.c~1_MV_REPORTING     2009-09-12 02:03:21.000000000 
+0200
+++ __UTRACE/kernel/utrace.c    2009-09-12 02:24:27.000000000 +0200
@@ -584,14 +584,14 @@ int utrace_set_events(struct task_struct
        if (!utrace->stopped && target != current && !target->exit_state) {
                /*
                 * This barrier ensures that our engine->flags changes
-                * have hit before we examine utrace->reporting,
+                * have hit before we examine engine->reporting,
                 * pairing with the barrier in start_callback().  If
                 * @target has not yet hit finish_callback() to clear
-                * utrace->reporting, we might be in the middle of a
+                * engine->reporting, we might be in the middle of a
                 * callback to @engine.
                 */
                smp_mb();
-               if (utrace->reporting == engine)
+               if (engine->reporting)
                        ret = -EINPROGRESS;
        }
 
@@ -1065,13 +1065,13 @@ int utrace_control(struct task_struct *t
                        /*
                         * As in utrace_set_events(), this barrier ensures
                         * that our engine->flags changes have hit before we
-                        * examine utrace->reporting, pairing with the barrier
+                        * examine engine->reporting, pairing with the barrier
                         * in start_callback().  If @target has not yet hit
-                        * finish_callback() to clear utrace->reporting, we
+                        * finish_callback() to clear engine->reporting, we
                         * might be in the middle of a callback to @engine.
                         */
                        smp_mb();
-                       if (utrace->reporting == engine)
+                       if (engine->reporting)
                                ret = -EINPROGRESS;
                }
                break;
@@ -1228,12 +1228,12 @@ int utrace_barrier(struct task_struct *t
                         * worry about @target making a callback.
                         * When it has entered start_callback() but
                         * not yet gotten to finish_callback(), we
-                        * will see utrace->reporting == @engine.
+                        * will see @engine->reporting == true.
                         * When @target doesn't take the lock, it uses
-                        * barriers to order setting utrace->reporting
+                        * barriers to order setting engine->reporting
                         * before it examines the engine state.
                         */
-                       if (utrace->reporting != engine)
+                       if (!engine->reporting)
                                ret = 0;
                        spin_unlock(&utrace->lock);
                        if (!ret)
@@ -1384,9 +1384,9 @@ static bool finish_callback(struct task_
         * We don't need any barriers here because utrace_barrier()
         * takes utrace->lock.  If we touched engine->flags above,
         * the lock guaranteed this change was before utrace_barrier()
-        * examined utrace->reporting.
+        * examined engine->reporting.
         */
-       utrace->reporting = NULL;
+       engine->reporting = false;
 
        /*
         * This is a good place to make sure tracing engines don't
@@ -1414,13 +1414,13 @@ static const struct utrace_engine_ops *s
        unsigned long want;
 
        /*
-        * This barrier ensures that we've set utrace->reporting before
+        * This barrier ensures that we've set engine->reporting before
         * we examine engine->flags or engine->ops.  utrace_barrier()
         * relies on this ordering to indicate that the effect of any
         * utrace_control() and utrace_set_events() calls is in place
-        * by the time utrace->reporting can be seen to be NULL.
+        * by the time engine->reporting can be seen to be NULL.
         */
-       utrace->reporting = engine;
+       engine->reporting = true;
        smp_mb();
 
        /*
@@ -1440,13 +1440,13 @@ static const struct utrace_engine_ops *s
                        return NULL;
 
                /*
-                * finish_callback() reset utrace->reporting after the
+                * finish_callback() reset engine->reporting after the
                 * quiesce callback.  Now we set it again (as above)
                 * before re-examining engine->flags, which could have
                 * been changed synchronously by ->report_quiesce or
                 * asynchronously by utrace_control() or utrace_set_events().
                 */
-               utrace->reporting = engine;
+               engine->reporting = true;
                smp_mb();
                want = engine->flags;
        }
@@ -1459,7 +1459,7 @@ static const struct utrace_engine_ops *s
                return ops;
        }
 
-       utrace->reporting = NULL;
+       engine->reporting = false;
        return NULL;
 }
 
@@ -2013,7 +2013,7 @@ int utrace_get_signal(struct task_struct
                /*
                 * See start_callback() comment about this barrier.
                 */
-               utrace->reporting = engine;
+               engine->reporting = true;
                smp_mb();
 
                /*
@@ -2025,7 +2025,7 @@ int utrace_get_signal(struct task_struct
                ops = engine->ops;
 
                if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) {
-                       utrace->reporting = NULL;
+                       engine->reporting = false;
                        continue;
                }
 

Reply via email to