summaryrefslogtreecommitdiffstats
path: root/runtime/task_finder_vma.c
diff options
context:
space:
mode:
authorDavid Smith <dsmith@redhat.com>2008-06-23 12:41:45 -0500
committerDavid Smith <dsmith@redhat.com>2008-06-23 12:43:23 -0500
commita21d81ec8b00571cb5987fe04ce74a3fe873351c (patch)
treed38eae80a5cfaf3cb5bdf0a8da6cbe0b8b98cd88 /runtime/task_finder_vma.c
parentb857a3649c0f8e4e2d8a7209424f23c5d55adac7 (diff)
downloadsystemtap-steved-a21d81ec8b00571cb5987fe04ce74a3fe873351c.tar.gz
systemtap-steved-a21d81ec8b00571cb5987fe04ce74a3fe873351c.tar.xz
systemtap-steved-a21d81ec8b00571cb5987fe04ce74a3fe873351c.zip
Major update to memory map change notification code.
2008-06-23 David Smith <dsmith@redhat.com> * tapsets.cxx (utrace_derived_probe_group::emit_probe_decl): Handles UDPF_NONE value. (utrace_derived_probe_group::emit_vm_callback_probe_decl): New function. (utrace_derived_probe_group::emit_module_decls): Calls emit_vm_callback_probe_decl() to set up vm_callbacks. 2008-06-23 David Smith <dsmith@redhat.com> * task_finder.c (__stp_tf_vm_cb): New function. (stap_register_task_finder_target): Sets up syscall entry and syscall exit handlers. (__stp_find_file_based_vma): New function. (__stp_utrace_task_finder_target_syscall_entry): New function. Saves vma information off at syscall entry. (__stp_target_call_vm_callback): New function. (__stp_utrace_task_finder_target_syscall_exit): New function. Handles changes to memory maps based on information saved at syscall entry. * syscall.h: New file containing syscall function. * task_finder_vma.c: New file containing saved vma information handling functions.
Diffstat (limited to 'runtime/task_finder_vma.c')
-rw-r--r--runtime/task_finder_vma.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c
new file mode 100644
index 00000000..c849f187
--- /dev/null
+++ b/runtime/task_finder_vma.c
@@ -0,0 +1,112 @@
+#include <linux/list.h>
+#include <linux/jhash.h>
+#include <linux/mutex.h>
+
+// __stp_tf_vma_mutex protects the hash table.
+static DEFINE_MUTEX(__stp_tf_vma_mutex);
+
+#define __STP_TF_HASH_BITS 4
+#define __STP_TF_TABLE_SIZE (1 << __STP_TF_HASH_BITS)
+
+struct __stp_tf_vma_entry {
+ struct hlist_node hlist;
+
+ pid_t pid;
+ unsigned long addr;
+ unsigned long vm_start;
+ unsigned long vm_end;
+ unsigned long vm_pgoff;
+ // Is that enough? Should we store a dcookie for vm_file?
+};
+
+static struct hlist_head __stp_tf_vma_table[__STP_TF_TABLE_SIZE];
+
+static inline u32
+__stp_tf_vma_hash(struct task_struct *tsk, unsigned long addr)
+{
+#if (__SIZEOF_LONG__ == 8)
+ return (jhash_3words(tsk->pid, (u32)addr, (u32)(addr >> 32), 0)
+ & (__STP_TF_TABLE_SIZE - 1));
+#else
+ return (jhash_2words(tsk->pid, addr, 0) & (__STP_TF_TABLE_SIZE - 1));
+#endif
+}
+
+
+// Get vma_entry if the vma is present in the vma hash table.
+// Returns NULL if not present.
+static struct __stp_tf_vma_entry *
+__stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct __stp_tf_vma_entry *entry;
+
+ mutex_lock(&__stp_tf_vma_mutex);
+ head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ if (tsk->pid == entry->pid
+ && addr == entry->addr) {
+ mutex_unlock(&__stp_tf_vma_mutex);
+ return entry;
+ }
+ }
+ mutex_unlock(&__stp_tf_vma_mutex);
+ return NULL;
+}
+
+// Add the vma info to the vma hash table.
+static int
+__stp_tf_add_vma(struct task_struct *tsk, unsigned long addr,
+ struct vm_area_struct *vma)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct __stp_tf_vma_entry *entry;
+
+ mutex_lock(&__stp_tf_vma_mutex);
+ head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ if (tsk->pid == entry->pid
+ && addr == entry->addr) {
+ printk(KERN_NOTICE
+ "vma (pid: %d, vm_start: 0x%lx) present?\n",
+ tsk->pid, vma->vm_start);
+ mutex_unlock(&__stp_tf_vma_mutex);
+ return -EBUSY; /* Already there */
+ }
+ }
+
+ // Using kmalloc here to allocate an element. Could cause some
+ // memory fragmentation if overused.
+ entry = kmalloc(sizeof(struct __stp_tf_vma_entry), GFP_KERNEL);
+ if (!entry) {
+ mutex_unlock(&__stp_tf_vma_mutex);
+ return -ENOMEM;
+ }
+ entry->pid = tsk->pid;
+ entry->addr = addr;
+ entry->vm_start = vma->vm_start;
+ entry->vm_end = vma->vm_end;
+ entry->vm_pgoff = vma->vm_pgoff;
+ hlist_add_head(&entry->hlist, head);
+ mutex_unlock(&__stp_tf_vma_mutex);
+ return 0;
+}
+
+// Remove the vma entry from the vma hash table.
+static int
+__stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ int found = 0;
+
+ if (entry != NULL) {
+ mutex_lock(&__stp_tf_vma_mutex);
+ hlist_del(&entry->hlist);
+ kfree(entry);
+ mutex_unlock(&__stp_tf_vma_mutex);
+ }
+ return 0;
+}