X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Flinux%2Futrace.h;h=c7987050caf36baa8e719fe748d282357cc38eb1;hb=refs%2Fheads%2Fvserver;hp=f310aa37a94a794ac6f18c0085a548005caa9748;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/include/linux/utrace.h b/include/linux/utrace.h index f310aa37a..c7987050c 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -1,5 +1,13 @@ /* - * User Debugging Data & Event Rendezvous + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006, 2007 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 + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. * * This interface allows for notification of interesting events in a thread. * It also mediates access to thread state such as registers. @@ -38,9 +46,11 @@ #include #include #include +#include struct linux_binprm; struct pt_regs; +struct utrace; struct utrace_regset; struct utrace_regset_view; @@ -167,6 +177,8 @@ enum utrace_events { #define UTRACE_ATTACH_MATCH_MASK 0x000f +#ifdef CONFIG_UTRACE + /* * Per-thread structure task_struct.utrace points to. * @@ -190,16 +202,13 @@ struct utrace struct utrace_signal *signal; } live; struct { - int notified; - int reap; + unsigned long flags; } exit; } u; struct list_head engines; spinlock_t lock; }; -#define utrace_lock(utrace) spin_lock(&(utrace)->lock) -#define utrace_unlock(utrace) spin_unlock(&(utrace)->lock) /* @@ -208,7 +217,7 @@ struct utrace * The task itself never has to worry about engines detaching while * it's doing event callbacks. These structures are freed only when * the task is quiescent. For other parties, the list is protected - * by RCU and utrace_lock. + * by RCU and utrace->lock. */ struct utrace_attached_engine { @@ -334,6 +343,17 @@ struct utrace_engine_ops * by its parent, or self-reap immediately. Though the actual * reaping may happen in parallel, a report_reap callback will * always be ordered after a report_death callback. + * + * If UTRACE_ACTION_NOREAP is in force and this was a group_leader + * dying with other threads still in the group (delayed_group_leader), + * then there can be a second report_death callback later when the + * group_leader is no longer delayed. This second callback can be + * made from another thread's context, but it will always be + * serialized after the first report_death callback and before the + * report_reap callback. It's possible that delayed_group_leader will + * already be true by the time it can be checked inside the first + * report_death callback made at the time of death, but that a second + * callback will be made almost immediately thereafter. */ u32 (*report_death)(struct utrace_attached_engine *engine, struct task_struct *tsk); @@ -416,11 +436,16 @@ struct utrace_attached_engine *utrace_attach(struct task_struct *target, * * If the target thread is not already quiescent, then a callback to this * engine might be in progress or about to start on another CPU. If it's - * quiescent when utrace_detach is called, then after return it's guaranteed - * that no more callbacks to the ops vector will be done. + * quiescent when utrace_detach is called, then after successful return + * it's guaranteed that no more callbacks to the ops vector will be done. + * The only exception is SIGKILL (and exec by another thread in the group), + * which breaks quiescence and can cause asynchronous DEATH and/or REAP + * callbacks even when UTRACE_ACTION_QUIESCE is set. In that event, + * utrace_detach fails with -ESRCH or -EALREADY to indicate that the + * report_reap or report_death callbacks have begun or will run imminently. */ -void utrace_detach(struct task_struct *target, - struct utrace_attached_engine *engine); +int utrace_detach(struct task_struct *target, + struct utrace_attached_engine *engine); /* * Change the flags for a tracing engine. @@ -429,10 +454,25 @@ void utrace_detach(struct task_struct *target, * this will cause a report_quiesce callback soon, maybe immediately. * If UTRACE_ACTION_QUIESCE was set before and is no longer set by * any engine, this will wake the thread up. + * + * This fails with -EALREADY and does nothing if you try to clear + * UTRACE_EVENT(DEATH) when the report_death callback may already have + * begun, if you try to clear UTRACE_EVENT(REAP) when the report_reap + * callback may already have begun, if you try to newly set + * UTRACE_ACTION_NOREAP when the target may already have sent its + * parent SIGCHLD, or if you try to newly set UTRACE_EVENT(DEATH), + * UTRACE_EVENT(QUIESCE), or UTRACE_ACTION_QUIESCE, when the target is + * already dead or dying. It can fail with -ESRCH when the target has + * already been detached (including forcible detach on reaping). If + * the target was quiescent before the call, then after a successful + * call, no event callbacks not requested in the new flags will be + * made, and a report_quiesce callback will always be made if + * requested. These rules provide for coherent synchronization based + * on quiescence, even when SIGKILL is breaking quiescence. */ -void utrace_set_flags(struct task_struct *target, - struct utrace_attached_engine *engine, - unsigned long flags); +int utrace_set_flags(struct task_struct *target, + struct utrace_attached_engine *engine, + unsigned long flags); /* * Cause a specified signal delivery in the target thread, which must be @@ -472,6 +512,7 @@ void utrace_report_clone(unsigned long clone_flags, struct task_struct *child); void utrace_report_vfork_done(pid_t child_pid); void utrace_report_exit(long *exit_code); void utrace_report_death(struct task_struct *, struct utrace *); +void utrace_report_delayed_group_leader(struct task_struct *); int utrace_report_jctl(int type); void utrace_report_exec(struct linux_binprm *bprm, struct pt_regs *regs); void utrace_report_syscall(struct pt_regs *regs, int is_exit); @@ -480,5 +521,114 @@ int utrace_allow_access_process_vm(struct task_struct *); int utrace_unsafe_exec(struct task_struct *); void utrace_signal_handler_singlestep(struct task_struct *, struct pt_regs *); +/* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ +static inline unsigned long tsk_utrace_flags(struct task_struct *tsk) +{ + return tsk->utrace_flags; +} +static inline struct utrace *tsk_utrace_struct(struct task_struct *tsk) +{ + return tsk->utrace; +} +static inline void utrace_init_task(struct task_struct *child) +{ + child->utrace_flags = 0; + child->utrace = NULL; +} + +#else /* !CONFIG_UTRACE */ + +static unsigned long tsk_utrace_flags(struct task_struct *tsk) +{ + return 0; +} +static struct utrace *tsk_utrace_struct(struct task_struct *tsk) +{ + return NULL; +} +static inline void utrace_init_task(struct task_struct *child) +{ +} + +/* + * The calls to these should all be in if (0) and optimized out entirely. + * We have stubs here only so tracehook.h doesn't need to #ifdef them + * to avoid external references in case of unoptimized compilation. + */ +static inline int utrace_quiescent(struct task_struct *tsk, void *ignored) +{ + BUG(); + return 0; +} +static inline void utrace_release_task(struct task_struct *tsk) +{ + BUG(); +} +static inline int utrace_get_signal(struct task_struct *tsk, + struct pt_regs *regs, + siginfo_t *info, struct k_sigaction *ka) +{ + BUG(); + return 0; +} +static inline void utrace_report_clone(unsigned long clone_flags, + struct task_struct *child) +{ + BUG(); +} +static inline void utrace_report_vfork_done(pid_t child_pid) +{ + BUG(); +} +static inline void utrace_report_exit(long *exit_code) +{ + BUG(); +} +static inline void utrace_report_death(struct task_struct *tsk, void *ignored) +{ + BUG(); +} +static inline void utrace_report_delayed_group_leader(struct task_struct *tsk) +{ + BUG(); +} +static inline int utrace_report_jctl(int type) +{ + BUG(); + return 0; +} +static inline void utrace_report_exec(struct linux_binprm *bprm, + struct pt_regs *regs) +{ + BUG(); +} +static inline void utrace_report_syscall(struct pt_regs *regs, int is_exit) +{ + BUG(); +} +static inline struct task_struct *utrace_tracer_task(struct task_struct *tsk) +{ + BUG(); + return NULL; +} +static inline int utrace_allow_access_process_vm(struct task_struct *tsk) +{ + BUG(); + return 0; +} +static inline int utrace_unsafe_exec(struct task_struct *tsk) +{ + BUG(); + return 0; +} +static inline void utrace_signal_handler_singlestep(struct task_struct *tsk, + struct pt_regs *regs) +{ + BUG(); +} + +#endif /* CONFIG_UTRACE */ #endif /* linux/utrace.h */