On 03/12, Roland McGrath wrote: > > So I think we need this: > > @@ -181,7 +181,13 @@ static int utrace_add_engine(struct task_struct *target, > * also set. Otherwise utrace_control() or utrace_do_stop() > * might skip setting TIF_NOTIFY_RESUME upon seeing ->report > * already set, and we'd miss a necessary callback. > + * > + * In case we had no engines before, make sure that > + * utrace_flags is not zero when tracehook_notify_resume() > + * checks. That would bypass utrace reporting clearing > + * TIF_NOTIFY_RESUME, and thus violate the same invariant. > */ > + target->utrace_flags |= UTRACE_EVENT(REAP); > list_add_tail(&engine->entry, &utrace->attaching); > utrace->report = 1; > set_notify_resume(target);
Agreed. > Does that need a barrier pair here and in No, set_notify_resume()->test_and_set_tsk_thread_flag() implies mb(), > tracehook_notify_resume()? Ah. I think you are right, and I think it needs the barrier even without this change. Say, UTRACE_REPORT does: utrace->report = 1; set_notify_resume(); Without mb() there is no guarantee that utrace_resume() will notice and clear ->report. smp_mb__after_clear_bit() is enough, but in that case perhaps it is better to modify the arch dependent do_notify_resume(). A couple of minor nits, but please remember I often misread the comments. > Sure, better comments are always good. How's this? > > @@ -899,6 +899,10 @@ static void utrace_reset(struct task_struct *task, > struct utrace *utrace, > * of the interests of the remaining tracing engines. > * For any engine marked detached, remove it from the list. > * We'll collect them on the detached list. > + * > + * Any engine that's not detached implies tracking the REAP event, > + * whether or not that engine wants a report_reap callback. Any > + * engine requires attention from utrace_release_task(). > */ > list_for_each_entry_safe(engine, next, &utrace->attached, entry) { This looks misleading, utrace_release_task() is called unconditionally, and we could use any unused bit afacis (REAP only makes sense for engine->flags, we never check ->utrace_flags & REAP). Also, whatever reason we have to keep ->utrace_flags != 0, the same reason applies to ->utrace_flags |= XXX in utrace_add_engine(). utrace_reset() also does if (task->exit_state) { flags &= DEAD_FLAGS_MASK; The comment about DEAD_FLAGS_MASK /* * Only these flags matter any more for a dead task (exit_state set). * We use this mask on flags installed in ->utrace_flags after * exit_notify (and possibly utrace_report_death) has run. Looks a bit confusing to me. Unless exit_notify() calls utrace_report_death() we don't change ->utrace_flags. * This ensures that utrace_release_task knows positively that * utrace_report_death will not run later. */ Yes. But this means we could do "flags &= ~DEATH_EVENTS" instead. This is subjective of course, but looks more clean to me. Note also that utrace_reset() is the only user of DEAD_FLAGS_MASK and LIVE_FLAGS_MASK has no users. Also, it would be better imho to change tracehook_report_death() to use DEATH_EVENTS too, it is always good when grep can find the usage. Oleg.