rcu: Stopgap fix for synchronize_rcu_expedited() for TREE_PREEMPT_RCU
[safe/jmp/linux-2.6] / include / linux / tracehook.h
index 589f429..1eb44a9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Tracing hooks
  *
- * Copyright (C) 2008 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2008-2009 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -143,7 +143,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
  *
  * Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
  *
- * Called with task_lock() held on @task.
+ * @task->cred_guard_mutex is held by the caller through the do_execve().
  */
 static inline int tracehook_unsafe_exec(struct task_struct *task)
 {
@@ -244,7 +244,7 @@ static inline int tracehook_prepare_clone(unsigned clone_flags)
  * tracehook_finish_clone - new child created and being attached
  * @child:             new child task
  * @clone_flags:       %CLONE_* flags from clone/fork/vfork system call
- * @trace:             return value from tracehook_clone_prepare()
+ * @trace:             return value from tracehook_prepare_clone()
  *
  * This is called immediately after adding @child to its parent's children list.
  * The @trace value is that returned by tracehook_prepare_clone().
@@ -259,29 +259,29 @@ static inline void tracehook_finish_clone(struct task_struct *child,
 
 /**
  * tracehook_report_clone - in parent, new child is about to start running
- * @trace:             return value from tracehook_clone_prepare()
  * @regs:              parent's user register state
  * @clone_flags:       flags from parent's system call
  * @pid:               new child's PID in the parent's namespace
  * @child:             new child task
  *
  * Called after a child is set up, but before it has been started running.
- * The @trace value is that returned by tracehook_clone_prepare().
- * This is not a good place to block, because the child has not started yet.
- * Suspend the child here if desired, and block in tracehook_clone_complete().
- * This must prevent the child from self-reaping if tracehook_clone_complete()
- * uses the @child pointer; otherwise it might have died and been released by
- * the time tracehook_report_clone_complete() is called.
+ * This is not a good place to block, because the child has not started
+ * yet.  Suspend the child here if desired, and then block in
+ * tracehook_report_clone_complete().  This must prevent the child from
+ * self-reaping if tracehook_report_clone_complete() uses the @child
+ * pointer; otherwise it might have died and been released by the time
+ * tracehook_report_clone_complete() is called.
  *
  * Called with no locks held, but the child cannot run until this returns.
  */
-static inline void tracehook_report_clone(int trace, struct pt_regs *regs,
+static inline void tracehook_report_clone(struct pt_regs *regs,
                                          unsigned long clone_flags,
                                          pid_t pid, struct task_struct *child)
 {
-       if (unlikely(trace)) {
+       if (unlikely(task_ptrace(child))) {
                /*
-                * The child starts up with an immediate SIGSTOP.
+                * It doesn't matter who attached/attaching to this
+                * task, the pending SIGSTOP is right in any case.
                 */
                sigaddset(&child->pending.signal, SIGSTOP);
                set_tsk_thread_flag(child, TIF_SIGPENDING);
@@ -290,7 +290,7 @@ static inline void tracehook_report_clone(int trace, struct pt_regs *regs,
 
 /**
  * tracehook_report_clone_complete - new child is running
- * @trace:             return value from tracehook_clone_prepare()
+ * @trace:             return value from tracehook_prepare_clone()
  * @regs:              parent's user register state
  * @clone_flags:       flags from parent's system call
  * @pid:               new child's PID in the parent's namespace
@@ -347,7 +347,7 @@ static inline void tracehook_prepare_release_task(struct task_struct *task)
 }
 
 /**
- * tracehook_finish_release_task - task is being reaped, clean up tracing
+ * tracehook_finish_release_task - final tracing clean-up
  * @task:              task in %EXIT_DEAD state
  *
  * This is called in release_task() when @task is being in the middle of
@@ -387,17 +387,14 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info,
  * tracehook_consider_ignored_signal - suppress short-circuit of ignored signal
  * @task:              task receiving the signal
  * @sig:               signal number being sent
- * @handler:           %SIG_IGN or %SIG_DFL
  *
  * Return zero iff tracing doesn't care to examine this ignored signal,
  * so it can short-circuit normal delivery and never even get queued.
- * Either @handler is %SIG_DFL and @sig's default is ignore, or it's %SIG_IGN.
  *
  * Called with @task->sighand->siglock held.
  */
 static inline int tracehook_consider_ignored_signal(struct task_struct *task,
-                                                   int sig,
-                                                   void __user *handler)
+                                                   int sig)
 {
        return (task_ptrace(task) & PT_PTRACED) != 0;
 }
@@ -406,19 +403,17 @@ static inline int tracehook_consider_ignored_signal(struct task_struct *task,
  * tracehook_consider_fatal_signal - suppress special handling of fatal signal
  * @task:              task receiving the signal
  * @sig:               signal number being sent
- * @handler:           %SIG_DFL or %SIG_IGN
  *
  * Return nonzero to prevent special handling of this termination signal.
- * Normally @handler is %SIG_DFL.  It can be %SIG_IGN if @sig is ignored,
- * in which case force_sig() is about to reset it to %SIG_DFL.
+ * Normally handler for signal is %SIG_DFL.  It can be %SIG_IGN if @sig is
+ * ignored, in which case force_sig() is about to reset it to %SIG_DFL.
  * When this returns zero, this signal might cause a quick termination
  * that does not give the debugger a chance to intercept the signal.
  *
  * Called with or without @task->sighand->siglock held.
  */
 static inline int tracehook_consider_fatal_signal(struct task_struct *task,
-                                                 int sig,
-                                                 void __user *handler)
+                                                 int sig)
 {
        return (task_ptrace(task) & PT_PTRACED) != 0;
 }
@@ -468,40 +463,62 @@ static inline int tracehook_get_signal(struct task_struct *task,
 
 /**
  * tracehook_notify_jctl - report about job control stop/continue
- * @notify:            nonzero if this is the last thread in the group to stop
+ * @notify:            zero, %CLD_STOPPED or %CLD_CONTINUED
  * @why:               %CLD_STOPPED or %CLD_CONTINUED
  *
  * This is called when we might call do_notify_parent_cldstop().
- * It's called when about to stop for job control; we are already in
- * %TASK_STOPPED state, about to call schedule().  It's also called when
- * a delayed %CLD_STOPPED or %CLD_CONTINUED report is ready to be made.
  *
- * Return nonzero to generate a %SIGCHLD with @why, which is
- * normal if @notify is nonzero.
+ * @notify is zero if we would not ordinarily send a %SIGCHLD,
+ * or is the %CLD_STOPPED or %CLD_CONTINUED .si_code for %SIGCHLD.
  *
- * Called with no locks held.
+ * @why is %CLD_STOPPED when about to stop for job control;
+ * we are already in %TASK_STOPPED state, about to call schedule().
+ * It might also be that we have just exited (check %PF_EXITING),
+ * but need to report that a group-wide stop is complete.
+ *
+ * @why is %CLD_CONTINUED when waking up after job control stop and
+ * ready to make a delayed @notify report.
+ *
+ * Return the %CLD_* value for %SIGCHLD, or zero to generate no signal.
+ *
+ * Called with the siglock held.
  */
 static inline int tracehook_notify_jctl(int notify, int why)
 {
-       return notify || (current->ptrace & PT_PTRACED);
+       return notify ?: (current->ptrace & PT_PTRACED) ? why : 0;
 }
 
 /**
+ * tracehook_finish_jctl - report about return from job control stop
+ *
+ * This is called by do_signal_stop() after wakeup.
+ */
+static inline void tracehook_finish_jctl(void)
+{
+}
+
+#define DEATH_REAP                     -1
+#define DEATH_DELAYED_GROUP_LEADER     -2
+
+/**
  * tracehook_notify_death - task is dead, ready to notify parent
  * @task:              @current task now exiting
  * @death_cookie:      value to pass to tracehook_report_death()
  * @group_dead:                nonzero if this was the last thread in the group to die
  *
- * Return the signal number to send our parent with do_notify_parent(), or
- * zero to send no signal and leave a zombie, or -1 to self-reap right now.
+ * A return value >= 0 means call do_notify_parent() with that signal
+ * number.  Negative return value can be %DEATH_REAP to self-reap right
+ * now, or %DEATH_DELAYED_GROUP_LEADER to a zombie without notifying our
+ * parent.  Note that a return value of 0 means a do_notify_parent() call
+ * that sends no signal, but still wakes up a parent blocked in wait*().
  *
  * Called with write_lock_irq(&tasklist_lock) held.
  */
 static inline int tracehook_notify_death(struct task_struct *task,
                                         void **death_cookie, int group_dead)
 {
-       if (task->exit_signal == -1)
-               return task->ptrace ? SIGCHLD : -1;
+       if (task_detached(task))
+               return task->ptrace ? SIGCHLD : DEATH_REAP;
 
        /*
         * If something other than our normal parent is ptracing us, then
@@ -511,21 +528,21 @@ static inline int tracehook_notify_death(struct task_struct *task,
        if (thread_group_empty(task) && !ptrace_reparented(task))
                return task->exit_signal;
 
-       return task->ptrace ? SIGCHLD : 0;
+       return task->ptrace ? SIGCHLD : DEATH_DELAYED_GROUP_LEADER;
 }
 
 /**
  * tracehook_report_death - task is dead and ready to be reaped
  * @task:              @current task now exiting
- * @signal:            signal number sent to parent, or 0 or -1
+ * @signal:            return value from tracheook_notify_death()
  * @death_cookie:      value passed back from tracehook_notify_death()
  * @group_dead:                nonzero if this was the last thread in the group to die
  *
  * Thread has just become a zombie or is about to self-reap.  If positive,
  * @signal is the signal number just sent to the parent (usually %SIGCHLD).
- * If @signal is -1, this thread will self-reap.  If @signal is 0, this is
- * a delayed_group_leader() zombie.  The @death_cookie was passed back by
- * tracehook_notify_death().
+ * If @signal is %DEATH_REAP, this thread will self-reap.  If @signal is
+ * %DEATH_DELAYED_GROUP_LEADER, this is a delayed_group_leader() zombie.
+ * The @death_cookie was passed back by tracehook_notify_death().
  *
  * If normal reaping is not inhibited, @task->exit_state might be changing
  * in parallel.