As Peter pointed out, this barrier is not needed. utrace_set_events() and tracehook_report_death() can rely on tasklist_lock.
utrace_set_events() checks ->exit_state == 0 and adds DEATH_EVENTS under tasklist_lock. After exit_notify() sets ->exit_state under write_lock(tasklist) we must see the change in flags. utrace_set_events() does not set _UTRACE_DEATH_EVENTS if ->exit_state was already set by exit_notify(), and after we set ->exit_state under write_lock(tasklist) we must see the change in ->utrace_flags. Signed-off-by: Oleg Nesterov <o...@redhat.com> --- include/linux/tracehook.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) --- UTRACE-PTRACE/include/linux/tracehook.h~1_REPORT_DEATH_KILL_MB 2009-11-18 21:16:23.000000000 +0100 +++ UTRACE-PTRACE/include/linux/tracehook.h 2009-12-12 16:32:39.000000000 +0100 @@ -626,17 +626,12 @@ static inline void tracehook_report_deat int group_dead) { /* - * This barrier ensures that our caller's setting of - * @task->exit_state precedes checking @task->utrace_flags here. * If utrace_set_events() was just called to enable * UTRACE_EVENT(DEATH), then we are obliged to call * utrace_report_death() and not miss it. utrace_set_events() - * uses tasklist_lock to synchronize enabling the bit with the - * actual change to @task->exit_state, but we need this barrier - * to be sure we see a flags change made just before our caller - * took the tasklist_lock. + * checks @task->exit_state under tasklist_lock to synchronize + * with exit_notify(), the caller. */ - smp_mb(); if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) utrace_report_death(task, death_cookie, group_dead, signal); }