summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-02-15 14:29:08 -0500
committerFrank Ch. Eigler <fche@elastic.org>2008-02-15 14:29:08 -0500
commit0f05501579dc0a4e66ccbbd8e0b29d052d9b5920 (patch)
tree79bf8b7b328e87e8c30cc64e64a1bea9a6f2dca5 /runtime
parent044427bcdfa2a1d58a912bf96546892bef82b717 (diff)
parent275f40a6d612f94e5272eeed772e9c9294cb8e1f (diff)
downloadsystemtap-steved-0f05501579dc0a4e66ccbbd8e0b29d052d9b5920.tar.gz
systemtap-steved-0f05501579dc0a4e66ccbbd8e0b29d052d9b5920.tar.xz
systemtap-steved-0f05501579dc0a4e66ccbbd8e0b29d052d9b5920.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ChangeLog28
-rw-r--r--runtime/alloc.c9
-rw-r--r--runtime/counter.c4
-rw-r--r--runtime/io.c5
-rw-r--r--runtime/pmap-gen.c6
-rw-r--r--runtime/print_new.c5
-rw-r--r--runtime/stack-i386.c2
-rw-r--r--runtime/stack-ia64.c4
-rw-r--r--runtime/staprun/staprun_funcs.c11
-rw-r--r--runtime/stat.c4
-rw-r--r--runtime/transport/ChangeLog4
-rw-r--r--runtime/transport/control.c8
-rw-r--r--runtime/transport/procfs.c6
-rw-r--r--runtime/transport/symbols.c2
-rw-r--r--runtime/uprobes/uprobes.c79
-rw-r--r--runtime/uprobes/uprobes.h3
16 files changed, 147 insertions, 33 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 7536cc88..b501c1ef 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,31 @@
+2008-02-06 Masami Hiramatsu <mhiramat@redhat.com>
+
+ * stack-ia64.c (__stp_show_stack_sym): Skip printing symbol if (ip ==
+ REG_IP(regs)).
+
+2008-01-29 Martin Hunt <hunt@redhat.com>
+
+ * io.c (_stp_vlog): Use get_cpu() instead
+ of smp_processor_id() because this function can get
+ called with interrupts enabled.
+
+2008-01-29 Martin Hunt <hunt@redhat.com>
+
+ * alloc.c (struct _stp_malloc_type): Remove
+ redundant field.
+
+2008-01-28 Martin Hunt <hunt@redhat.com>
+
+ * alloc.c: Use DEFINE_SPINLOCK.
+ * counter.c: Ditto.
+ * pmap-gen.c: Ditto.
+ * print_new.c: Ditto.
+ * stat.c: Ditto.
+
+2008-01-27 Frank Ch. Eigler <fche@elastic.org>
+
+ * stack-i386.c (__stp_stack_print): Correct #elif->#else typo.
+
2008-01-14 Martin Hunt <hunt@redhat.com>
* print.c (_stp_print_kernel_info): New function.
diff --git a/runtime/alloc.c b/runtime/alloc.c
index f022755a..cfdb97bd 100644
--- a/runtime/alloc.c
+++ b/runtime/alloc.c
@@ -32,7 +32,7 @@ static int _stp_allocated_net_memory = 0;
#ifdef DEBUG_MEM
-static spinlock_t _stp_mem_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(_stp_mem_lock);
static int _stp_allocated_memory = 0;
#define MEM_MAGIC 0xc11cf77f
@@ -41,15 +41,14 @@ static int _stp_allocated_memory = 0;
enum _stp_memtype { MEM_KMALLOC, MEM_VMALLOC, MEM_PERCPU };
typedef struct {
- enum _stp_memtype type;
char *alloc;
char *free;
} _stp_malloc_type;
static const _stp_malloc_type const _stp_malloc_types[] = {
- {MEM_KMALLOC, "kmalloc", "kfree"},
- {MEM_VMALLOC, "vmalloc", "vfree"},
- {MEM_PERCPU, "alloc_percpu", "free_percpu"}
+ {"kmalloc", "kfree"},
+ {"vmalloc", "vfree"},
+ {"alloc_percpu", "free_percpu"}
};
struct _stp_mem_entry {
diff --git a/runtime/counter.c b/runtime/counter.c
index 42555dfa..d0376547 100644
--- a/runtime/counter.c
+++ b/runtime/counter.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* Counter aggregation Functions
- * Copyright (C) 2005 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -60,7 +60,7 @@ Counter _stp_counter_init (void)
int i;
for_each_cpu(i) {
Counter c = per_cpu_ptr (cnt, i);
- c->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(c->lock);
}
}
#endif
diff --git a/runtime/io.c b/runtime/io.c
index e36381bd..c49d86e6 100644
--- a/runtime/io.c
+++ b/runtime/io.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* I/O for printing warnings, errors and debug messages
- * Copyright (C) 2005, 2006, 2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -25,7 +25,7 @@ enum code { INFO=0, WARN, ERROR, DBUG };
static void _stp_vlog (enum code type, const char *func, int line, const char *fmt, va_list args)
{
int num;
- char *buf = per_cpu_ptr(Stp_lbuf, smp_processor_id());
+ char *buf = per_cpu_ptr(Stp_lbuf, get_cpu());
int start = 0;
if (type == DBUG) {
@@ -53,6 +53,7 @@ static void _stp_vlog (enum code type, const char *func, int line, const char *f
_stp_print_flush();
}
}
+ put_cpu();
}
/** Logs Data.
diff --git a/runtime/pmap-gen.c b/runtime/pmap-gen.c
index ca8d45c5..0efffdb6 100644
--- a/runtime/pmap-gen.c
+++ b/runtime/pmap-gen.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* pmap API generator
- * Copyright (C) 2005-2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -412,7 +412,7 @@ PMAP KEYSYM(_stp_pmap_new) (unsigned max_entries)
m->copy = KEYSYM(pmap_copy_keys);
m->cmp = KEYSYM(pmap_key_cmp);
#if NEED_MAP_LOCKS
- m->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(m->lock);
#endif
}
m = &pmap->agg;
@@ -466,7 +466,7 @@ PMAP KEYSYM(_stp_pmap_new) (unsigned max_entries, int htype, ...)
m->copy = KEYSYM(pmap_copy_keys);
m->cmp = KEYSYM(pmap_key_cmp);
#if NEED_MAP_LOCKS
- m->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(m->lock);
#endif
}
m = &pmap->agg;
diff --git a/runtime/print_new.c b/runtime/print_new.c
index 95a83a8d..75bbd82b 100644
--- a/runtime/print_new.c
+++ b/runtime/print_new.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* Print Flush Function
- * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2007-2008 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -15,7 +15,8 @@
*
* @note Preemption must be disabled to use this.
*/
-spinlock_t _stp_print_lock = SPIN_LOCK_UNLOCKED;
+
+DEFINE_SPINLOCK(_stp_print_lock);
void EXPORT_FN(stp_print_flush) (_stp_pbuf *pb)
{
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index d73f4c84..b46ff06b 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -23,7 +23,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
{
#ifdef STAPCONF_X86_UNIREGS
unsigned long ebp = regs->bp;
- #elif
+ #else
unsigned long ebp = regs->ebp;
#endif
diff --git a/runtime/stack-ia64.c b/runtime/stack-ia64.c
index cab25a0b..ca9d25a6 100644
--- a/runtime/stack-ia64.c
+++ b/runtime/stack-ia64.c
@@ -23,8 +23,8 @@ static void __stp_show_stack_sym(struct unw_frame_info *info, void *arg)
if (skip){
if (ip == REG_IP(regs))
skip = 0;
- else continue;
- }
+ continue;
+ }
_stp_print_char(' ');
_stp_symbol_print(ip);
_stp_print_char('\n');
diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c
index d1bba3f8..3a678405 100644
--- a/runtime/staprun/staprun_funcs.c
+++ b/runtime/staprun/staprun_funcs.c
@@ -336,7 +336,11 @@ int check_permissions(void)
/* If neither group was found, just return an error. */
if (stapdev_gid == (gid_t)-1 && stapusr_gid == (gid_t)-1) {
- err("ERROR: unable to find either group \"stapdev\" or group \"stapusr\"\n");
+ err("ERROR: You are trying to run stap as a normal user.\n"
+ "You should either be root, or be part of either "
+ "group \"stapdev\" or group \"stapusr\".\n"
+ "Your system doesn't seem to have either group.\n"
+ "For more information, please consult the \"SAFETY AND SECURITY\" section of the \"stap(1)\" manpage\n");
return -1;
}
@@ -374,7 +378,10 @@ int check_permissions(void)
/* If path_check is 0, then the user isn't a member of either
* group. Error out. */
if (path_check == 0) {
- err("ERROR: you must be a member of either group \"stapdev\" or group \"stapusr\"\n");
+ err("ERROR: You are trying to run stap as a normal user.\n"
+ "You must be a member of either group \"stapdev\" or group \"stapusr\".\n"
+ "Please contact your system administrator to get yourself membership to either of those groups.\n"
+ "For more information, please consult the \"SAFETY AND SECURITY\" section of the \"stap(1)\" manpage.\n");
return 0;
}
diff --git a/runtime/stat.c b/runtime/stat.c
index 298a6653..f8b5f018 100644
--- a/runtime/stat.c
+++ b/runtime/stat.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* Statistics Aggregation
- * Copyright (C) 2005, 2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
* Copyright (C) 2006 Intel Corporation
*
* This file is part of systemtap, and is free software. You can
@@ -111,7 +111,7 @@ Stat _stp_stat_init (int type, ...)
int i;
for_each_cpu(i) {
stat *sdp = per_cpu_ptr (sd, i);
- sdp->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(sdp->lock);
}
}
#endif
diff --git a/runtime/transport/ChangeLog b/runtime/transport/ChangeLog
index e7bbabd8..764e3579 100644
--- a/runtime/transport/ChangeLog
+++ b/runtime/transport/ChangeLog
@@ -1,3 +1,7 @@
+2008-01-28 Martin Hunt <hunt@redhat.com>
+
+ * control.c, procfs.c, symbols.c: Use DEFINE_SPINLOCK
+
2008-01-15 Martin Hunt <hunt@redhat.com>
PR4037 and fixes to better synchronize staprun and stapio.
diff --git a/runtime/transport/control.c b/runtime/transport/control.c
index 3179f507..0bf99fc8 100644
--- a/runtime/transport/control.c
+++ b/runtime/transport/control.c
@@ -1,7 +1,7 @@
/* -*- linux-c -*-
*
* debugfs control channel
- * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2007-2008 Red Hat Inc.
*
* This file is part of systemtap, and is free software. You can
* redistribute it and/or modify it under the terms of the GNU General
@@ -15,9 +15,9 @@ static int _stp_current_buffers = STP_DEFAULT_BUFFERS;
static struct list_head _stp_ctl_ready_q;
static struct list_head _stp_sym_ready_q;
static struct list_head _stp_pool_q;
-spinlock_t _stp_pool_lock = SPIN_LOCK_UNLOCKED;
-spinlock_t _stp_ctl_ready_lock = SPIN_LOCK_UNLOCKED;
-spinlock_t _stp_sym_ready_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(_stp_pool_lock);
+DEFINE_SPINLOCK(_stp_ctl_ready_lock);
+DEFINE_SPINLOCK(_stp_sym_ready_lock);
static ssize_t _stp_sym_write_cmd (struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c
index 85e97d15..33f6db33 100644
--- a/runtime/transport/procfs.c
+++ b/runtime/transport/procfs.c
@@ -15,9 +15,9 @@ static int _stp_current_buffers = STP_DEFAULT_BUFFERS;
static struct list_head _stp_ctl_ready_q;
static struct list_head _stp_sym_ready_q;
static struct list_head _stp_pool_q;
-spinlock_t _stp_pool_lock = SPIN_LOCK_UNLOCKED;
-spinlock_t _stp_ctl_ready_lock = SPIN_LOCK_UNLOCKED;
-spinlock_t _stp_sym_ready_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(_stp_pool_lock);
+DEFINE_SPINLOCK(_stp_ctl_ready_lock);
+DEFINE_SPINLOCK(_stp_sym_ready_lock);
#ifdef STP_BULKMODE
extern int _stp_relay_flushing;
diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c
index dde0f967..e740dde8 100644
--- a/runtime/transport/symbols.c
+++ b/runtime/transport/symbols.c
@@ -16,7 +16,7 @@
#define _SYMBOLS_C_
#include "../sym.h"
-spinlock_t _stp_module_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(_stp_module_lock);
#define STP_TRYLOCK_MODULES ({ \
int numtrylock = 0; \
while (!spin_trylock_irqsave (&_stp_module_lock, flags) && (++numtrylock < MAXTRYLOCK)) \
diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c
index f0b72c46..f7d90add 100644
--- a/runtime/uprobes/uprobes.c
+++ b/runtime/uprobes/uprobes.c
@@ -94,6 +94,15 @@ struct deferred_registration {
enum uprobe_type type;
};
+/*
+ * Calling a signal handler cancels single-stepping, so uprobes delays
+ * calling the handler, as necessary, until after single-stepping is completed.
+ */
+struct delayed_signal {
+ struct list_head list;
+ siginfo_t info;
+};
+
static struct uprobe_task *uprobe_find_utask(struct task_struct *tsk)
{
struct hlist_head *head;
@@ -436,6 +445,7 @@ static int quiesce_all_threads(struct uprobe_process *uproc,
static void uprobe_free_task(struct uprobe_task *utask)
{
struct deferred_registration *dr, *d;
+ struct delayed_signal *ds, *ds2;
struct uretprobe_instance *ri;
struct hlist_node *r1, *r2;
@@ -445,6 +455,12 @@ static void uprobe_free_task(struct uprobe_task *utask)
list_del(&dr->list);
kfree(dr);
}
+
+ list_for_each_entry_safe(ds, ds2, &utask->delayed_signals, list) {
+ list_del(&ds->list);
+ kfree(ds);
+ }
+
hlist_for_each_entry_safe(ri, r1, r2, &utask->uretprobe_instances,
hlist) {
hlist_del(&ri->hlist);
@@ -557,6 +573,7 @@ static struct uprobe_task *uprobe_add_task(struct task_struct *t,
utask->doomed = 0;
INIT_HLIST_HEAD(&utask->uretprobe_instances);
INIT_LIST_HEAD(&utask->deferred_registrations);
+ INIT_LIST_HEAD(&utask->delayed_signals);
INIT_LIST_HEAD(&utask->list);
list_add_tail(&utask->list, &uproc->thread_list);
uprobe_hash_utask(utask);
@@ -1577,6 +1594,33 @@ static inline void uprobe_post_ssin(struct uprobe_task *utask,
/* uprobe_pre_ssout() and uprobe_post_ssout() are architecture-specific. */
/*
+ * Delay delivery of the indicated signal until after single-step.
+ * Otherwise single-stepping will be cancelled as part of calling
+ * the signal handler.
+ */
+static u32 uprobe_delay_signal(struct uprobe_task *utask, siginfo_t *info)
+{
+ struct delayed_signal *ds = kmalloc(sizeof(*ds), GFP_USER);
+ if (ds) {
+ ds->info = *info;
+ INIT_LIST_HEAD(&ds->list);
+ list_add_tail(&ds->list, &utask->delayed_signals);
+ }
+ return UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN |
+ UTRACE_ACTION_SINGLESTEP | UTRACE_ACTION_NEWSTATE;
+}
+
+static void uprobe_inject_delayed_signals(struct list_head *delayed_signals)
+{
+ struct delayed_signal *ds, *tmp;
+ list_for_each_entry_safe(ds, tmp, delayed_signals, list) {
+ send_sig_info(ds->info.si_signo, &ds->info, current);
+ list_del(&ds->list);
+ kfree(ds);
+ }
+}
+
+/*
* Signal callback:
*
* We get called here with:
@@ -1616,10 +1660,24 @@ static u32 uprobe_report_signal(struct utrace_attached_engine *engine,
unsigned long probept;
int hit_uretprobe_trampoline = 0;
int registrations_deferred = 0;
+ int uproc_freed = 0;
+ struct list_head delayed_signals;
utask = (struct uprobe_task *)rcu_dereference(engine->data);
BUG_ON(!utask);
+ /*
+ * info will be null if we're called with action=UTRACE_SIGNAL_HANDLER,
+ * which means that single-stepping has been disabled so a signal
+ * handler can be called in the probed process. That should never
+ * happen because we intercept and delay handled signals (action =
+ * UTRACE_ACTION_RESUME) until after we're done single-stepping.
+ */
+ BUG_ON(!info);
+ if (action == UTRACE_ACTION_RESUME && utask->active_probe &&
+ info->si_signo != SSTEP_SIGNAL)
+ return uprobe_delay_signal(utask, info);
+
if (info->si_signo != BREAKPOINT_SIGNAL &&
info->si_signo != SSTEP_SIGNAL)
goto no_interest;
@@ -1722,13 +1780,21 @@ bkpt_done:
uprobe_get_process(uproc);
}
+ /*
+ * Delayed signals are a little different. We want
+ * them delivered even if all the probes get unregistered
+ * and uproc and utask go away. So disconnect the list
+ * from utask and make it a local list.
+ */
+ INIT_LIST_HEAD(&delayed_signals);
+ list_splice_init(&utask->delayed_signals, &delayed_signals);
+
ret = UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN
| UTRACE_ACTION_NEWSTATE;
utask->state = UPTASK_RUNNING;
if (utask->quiescing) {
up_read(&uproc->rwsem);
- if (utask_fake_quiesce(utask) == 1)
- ret |= UTRACE_ACTION_DETACH;
+ uproc_freed |= utask_fake_quiesce(utask);
} else
up_read(&uproc->rwsem);
@@ -1738,12 +1804,17 @@ bkpt_done:
* we just recycled was the last reason for
* keeping uproc around.
*/
- uprobe_put_process(uproc);
+ uproc_freed |= uprobe_put_process(uproc);
if (registrations_deferred) {
uprobe_run_def_regs(&utask->deferred_registrations);
- uprobe_put_process(uproc);
+ uproc_freed |= uprobe_put_process(uproc);
}
+
+ uprobe_inject_delayed_signals(&delayed_signals);
+
+ if (uproc_freed)
+ ret |= UTRACE_ACTION_DETACH;
break;
default:
goto no_interest;
diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h
index 418518f8..0c471474 100644
--- a/runtime/uprobes/uprobes.h
+++ b/runtime/uprobes/uprobes.h
@@ -385,6 +385,9 @@ struct uprobe_task {
/* [un]registrations initiated by handlers must be asynchronous. */
struct list_head deferred_registrations;
+
+ /* Delay handler-destined signals 'til after single-step done. */
+ struct list_head delayed_signals;
};
#ifdef CONFIG_UPROBES_SSOL