From: pmf Date: Wed, 6 Aug 2008 17:46:53 +0000 (+0000) Subject: move obsolete ltt-modules to attic X-Git-Tag: v0.12.20~503 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=dc951cfe909fb6467b72ef6c6bbb04af736b91a1;p=lttv.git move obsolete ltt-modules to attic git-svn-id: http://ltt.polymtl.ca/svn@2986 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/trunk/attic/ltt-modules/Makefile b/trunk/attic/ltt-modules/Makefile new file mode 100644 index 00000000..0c56ebbb --- /dev/null +++ b/trunk/attic/ltt-modules/Makefile @@ -0,0 +1,24 @@ +ifneq ($(KERNELRELEASE),) +ifneq ($(CONFIG_LTT),) + obj-m := ltt-control.o ltt-statedump.o +endif + +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + KERNELRELEASE = $(shell cat $(KERNELDIR)/$(KBUILD_OUTPUT)/include/linux/version.h | sed -n 's/.*UTS_RELEASE.*\"\(.*\)\".*/\1/p') +ifneq ($(INSTALL_MOD_PATH),) + DEPMOD_OPT := -b $(INSTALL_MOD_PATH) +endif + +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +modules_install: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install + if [ -f $(KERNELDIR)/$(KBUILD_OUTPUT)/System.map ] ; then /sbin/depmod -ae -F $(KERNELDIR)/$(KBUILD_OUTPUT)/System.map $(DEPMOD_OPT) $(KERNELRELEASE) ; fi + + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean +endif diff --git a/trunk/attic/ltt-modules/ltt-control.c b/trunk/attic/ltt-modules/ltt-control.c new file mode 100644 index 00000000..45b44f0f --- /dev/null +++ b/trunk/attic/ltt-modules/ltt-control.c @@ -0,0 +1,115 @@ +/* ltt-control.c + * + * LTT control module over a netlink socket. + * + * Inspired from Relay Apps, by Tom Zanussi and iptables + * + * Copyright 2005 - + * Mathieu Desnoyers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ltt-control.h" + + +#define LTTCTLM_BASE 0x10 +#define LTTCTLM_CONTROL (LTTCTLM_BASE + 1) /* LTT control message */ + +static struct sock *socket; + +void ltt_control_input(struct sock *sk, int len) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh = NULL; + u8 *payload = NULL; + lttctl_peer_msg_t *msg; + int err; + + printk(KERN_ALERT "ltt-control ltt_control_input\n"); + + while ((skb = skb_dequeue(&sk->sk_receive_queue)) + != NULL) { + + nlh = (struct nlmsghdr *)skb->data; + + if(security_netlink_recv(skb)) { + netlink_ack(skb, nlh, EPERM); + kfree_skb(skb); + continue; + } + + /* process netlink message pointed by skb->data */ + err = EINVAL; + payload = NLMSG_DATA(nlh); + /* process netlink message with header pointed by + * nlh and payload pointed by payload + */ + if(nlh->nlmsg_len != sizeof(lttctl_peer_msg_t) + sizeof(struct nlmsghdr)) { + printk(KERN_ALERT "ltt-control bad message length\n"); + netlink_ack(skb, nlh, EINVAL); + kfree_skb(skb); + continue; + } + msg = (lttctl_peer_msg_t*)payload; + + switch(msg->op) { + case OP_CREATE: + err = ltt_control(LTT_CONTROL_CREATE_TRACE, msg->trace_name, + msg->args); + break; + case OP_DESTROY: + err = ltt_control(LTT_CONTROL_DESTROY_TRACE, msg->trace_name, + msg->args); + break; + case OP_START: + err = ltt_control(LTT_CONTROL_START, msg->trace_name, + msg->args); + break; + case OP_STOP: + err = ltt_control(LTT_CONTROL_STOP, msg->trace_name, + msg->args); + break; + default: + err = EBADRQC; + printk(KERN_INFO "ltt-control invalid operation\n"); + } + netlink_ack(skb, nlh, err); + kfree_skb(skb); + } +} + + +static int ltt_control_init(void) +{ + printk(KERN_ALERT "ltt-control init\n"); + + socket = netlink_kernel_create(NETLINK_LTT, 1, + ltt_control_input, THIS_MODULE); + if(socket == NULL) return -EPERM; + else return 0; +} + +static void ltt_control_exit(void) +{ + printk(KERN_ALERT "ltt-control exit\n"); + + sock_release(socket->sk_socket); +} + + +module_init(ltt_control_init) +module_exit(ltt_control_exit) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Linux Trace Toolkit Controller"); + diff --git a/trunk/attic/ltt-modules/ltt-control.h b/trunk/attic/ltt-modules/ltt-control.h new file mode 100644 index 00000000..430d5d12 --- /dev/null +++ b/trunk/attic/ltt-modules/ltt-control.h @@ -0,0 +1,26 @@ +#ifndef _LTT_CONTROL_H +#define _LTT_CONTROL_H + + +//enum trace_mode { +// TRACE_NORMAL, +// TRACE_FLIGHT +//}; + +enum trace_op { + OP_CREATE, + OP_DESTROY, + OP_START, + OP_STOP, + OP_ALIGN, + OP_NONE +}; + +typedef struct lttctl_peer_msg { + char trace_name[NAME_MAX]; + enum trace_op op; + union ltt_control_args args; +} lttctl_peer_msg_t; + +#endif //_LTT_CONTROL_H + diff --git a/trunk/attic/ltt-modules/ltt-statedump.c b/trunk/attic/ltt-modules/ltt-statedump.c new file mode 100644 index 00000000..d6c03217 --- /dev/null +++ b/trunk/attic/ltt-modules/ltt-statedump.c @@ -0,0 +1,352 @@ +/* ltt-state-dump.c + * + * Lunix Trace Toolkit Kernel State Dump + * + * Copyright 2005 - + * Jean-Hugues Deschenes + * + * Changes: + * Eric Clement: add listing of network IP interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NB_PROC_CHUNK 20 + +#include +#include + +/* in modules.c */ +extern int ltt_enumerate_modules(void); + +static inline int ltt_enumerate_network_ip_interface(void) +{ + struct net_device *list; + struct in_device *in_dev = NULL; + struct in_ifaddr *ifa = NULL; + + read_lock(&dev_base_lock); + for(list=dev_base; list != NULL; list=list->next) { + + if(list->flags & IFF_UP) { + in_dev = in_dev_get(list); + + if(in_dev) { + for (ifa = in_dev->ifa_list; ifa != NULL; ifa = ifa->ifa_next) { + trace_statedump_enumerate_network_ip_interface(list->name, + ifa->ifa_address, + LTTNG_UP); + } + in_dev_put(in_dev); + } + } else { + trace_statedump_enumerate_network_ip_interface(list->name, + 0, + LTTNG_DOWN); + } + } + read_unlock(&dev_base_lock); + + return 0; +} + +static inline int ltt_enumerate_file_descriptors(void) +{ + struct task_struct * t = &init_task; + unsigned int i; + struct file * filp; + char *tmp = (char*)__get_free_page(GFP_KERNEL), *path; + struct fdtable *fdt; + + /* Enumerate active file descriptors */ + + do { + read_lock(&tasklist_lock); + if(t != &init_task) atomic_dec(&t->usage); + t = next_task(t); + atomic_inc(&t->usage); + read_unlock(&tasklist_lock); + + task_lock(t); + if (t->files) { + spin_lock(&t->files->file_lock); + fdt = files_fdtable(t->files); + for (i=0; i < fdt->max_fds; i++) { + filp = fcheck_files(t->files, i); + if (!filp) + continue; + path = d_path(filp->f_dentry, filp->f_vfsmnt, tmp, PAGE_SIZE); + + /* Make sure we give at least some info */ + if(IS_ERR(path)) + trace_statedump_enumerate_file_descriptors(filp->f_dentry->d_name.name, t->pid, i); + else + trace_statedump_enumerate_file_descriptors(path, t->pid, i); + } + spin_unlock(&t->files->file_lock); + } + task_unlock(t); + + } while( t != &init_task ); + + free_page((unsigned long)tmp); + + return 0; +} + +static inline int ltt_enumerate_vm_maps(void) +{ + struct mm_struct *mm; + struct task_struct * t = &init_task; + struct vm_area_struct * map; + unsigned long ino = 0; + + do { + read_lock(&tasklist_lock); + if(t != &init_task) atomic_dec(&t->usage); + t = next_task(t); + atomic_inc(&t->usage); + read_unlock(&tasklist_lock); + + /* get_task_mm does a task_lock... */ + + mm = get_task_mm(t); + + if (mm) + { + map = mm->mmap; + + if(map) + { + down_read(&mm->mmap_sem); + + while (map) { + if (map->vm_file) { + ino = map->vm_file->f_dentry->d_inode->i_ino; + } else { + ino = 0; + } + + trace_statedump_enumerate_vm_maps(t->pid, (void *)map->vm_start, (void *)map->vm_end, map->vm_flags, map->vm_pgoff << PAGE_SHIFT, ino); + map = map->vm_next; + } + + up_read(&mm->mmap_sem); + } + + mmput(mm); + } + + } while( t != &init_task ); + + return 0; +} + +#if defined( CONFIG_ARM ) +/* defined in arch/arm/kernel/irq.c because of dependency on statically-defined lock & irq_desc */ +int ltt_enumerate_interrupts(void); +#else +static inline int ltt_enumerate_interrupts(void) +{ + unsigned int i; + unsigned long flags = 0; + + /* needs irq_desc */ + + for(i = 0; i < NR_IRQS; i++) + { + struct irqaction * action; + + spin_lock_irqsave(&irq_desc[i].lock, flags); + + + for (action=irq_desc[i].action; action; action = action->next) + trace_statedump_enumerate_interrupts( + irq_desc[i].handler->typename, + action->name, + i ); + + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } + + return 0; +} +#endif + +static inline int ltt_enumerate_process_states(void) +{ + struct task_struct * t = &init_task; + struct task_struct * p = t; + enum lttng_process_status status; + enum lttng_thread_type type; + enum lttng_execution_mode mode; + enum lttng_execution_submode submode; + + do { + mode = LTTNG_MODE_UNKNOWN; + submode = LTTNG_UNKNOWN; + + read_lock(&tasklist_lock); + if(t != &init_task) { + atomic_dec(&t->usage); + t = next_thread(t); + } + if(t == p) { + t = p = next_task(t); + } + atomic_inc(&t->usage); + read_unlock(&tasklist_lock); + + task_lock(t); + + if(t->exit_state == EXIT_ZOMBIE) + status = LTTNG_ZOMBIE; + else if(t->exit_state == EXIT_DEAD) + status = LTTNG_DEAD; + else if(t->state == TASK_RUNNING) + { + /* Is this a forked child that has not run yet? */ + if( list_empty(&t->run_list) ) + { + status = LTTNG_WAIT_FORK; + } + else + { + /* All tasks are considered as wait_cpu; the viewer will sort out if the task was relly running at this time. */ + status = LTTNG_WAIT_CPU; + } + } + else if(t->state & (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)) + { + /* Task is waiting for something to complete */ + status = LTTNG_WAIT; + } + else + status = LTTNG_UNNAMED; + + submode = LTTNG_NONE; + + + /* Verification of t->mm is to filter out kernel threads; + Viewer will further filter out if a user-space thread was in syscall mode or not */ + if(t->mm) + type = LTTNG_USER_THREAD; + else + type = LTTNG_KERNEL_THREAD; + + trace_statedump_enumerate_process_state(t->pid, t->parent->pid, t->comm, + type, mode, submode, status); + + task_unlock(t); + + } while( t != &init_task ); + + return 0; +} + +void ltt_statedump_work_func(void *sem) +{ + /* Our job is just to release the semaphore so + that we are sure that each CPU has been in syscall + mode before the end of ltt_statedump_thread */ + up((struct semaphore *)sem); +} + +static struct work_struct cpu_work[NR_CPUS]; + +int ltt_statedump_thread(void *data) +{ + struct semaphore work_sema4; + int cpu; + + printk("ltt_statedump_thread\n"); + + ltt_enumerate_process_states(); + + ltt_enumerate_file_descriptors(); + + ltt_enumerate_modules(); + + ltt_enumerate_vm_maps(); + + ltt_enumerate_interrupts(); + + ltt_enumerate_network_ip_interface(); + + /* Fire off a work queue on each CPU. Their sole purpose in life + * is to guarantee that each CPU has been in a state where is was in syscall + * mode (i.e. not in a trap, an IRQ or a soft IRQ) */ + sema_init(&work_sema4, 1 - num_online_cpus()); + + lock_cpu_hotplug(); + for_each_online_cpu(cpu) + { + INIT_WORK(&cpu_work[cpu], ltt_statedump_work_func, &work_sema4); + + schedule_delayed_work_on(cpu,&cpu_work[cpu],0); + } + unlock_cpu_hotplug(); + + /* Wait for all work queues to have completed */ + down(&work_sema4); + + /* Our work is done */ + printk("trace_statedump_statedump_end\n"); + trace_statedump_statedump_end(); + + do_exit(0); + + return 0; +} + +int ltt_statedump_start(struct ltt_trace_struct *trace) +{ + printk("ltt_statedump_start\n"); + + kthread_run( ltt_statedump_thread, + NULL, + "ltt_statedump"); + + return 0; +} + + +/* Dynamic facility. */ + +static int __init statedump_init(void) +{ + int ret; + printk(KERN_INFO "LTT : ltt-facility-statedump init\n"); + + ret = ltt_module_register(LTT_FUNCTION_STATEDUMP, + ltt_statedump_start,THIS_MODULE); + + return ret; +} + +static void __exit statedump_exit(void) +{ + ltt_module_unregister(LTT_FUNCTION_STATEDUMP); +} + +module_init(statedump_init) +module_exit(statedump_exit) + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jean-Hugues Deschenes"); +MODULE_DESCRIPTION("Linux Trace Toolkit Statedump"); + diff --git a/trunk/ltt-modules/Makefile b/trunk/ltt-modules/Makefile deleted file mode 100644 index 0c56ebbb..00000000 --- a/trunk/ltt-modules/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -ifneq ($(KERNELRELEASE),) -ifneq ($(CONFIG_LTT),) - obj-m := ltt-control.o ltt-statedump.o -endif - -else - KERNELDIR ?= /lib/modules/$(shell uname -r)/build - PWD := $(shell pwd) - KERNELRELEASE = $(shell cat $(KERNELDIR)/$(KBUILD_OUTPUT)/include/linux/version.h | sed -n 's/.*UTS_RELEASE.*\"\(.*\)\".*/\1/p') -ifneq ($(INSTALL_MOD_PATH),) - DEPMOD_OPT := -b $(INSTALL_MOD_PATH) -endif - -default: - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules - -modules_install: - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install - if [ -f $(KERNELDIR)/$(KBUILD_OUTPUT)/System.map ] ; then /sbin/depmod -ae -F $(KERNELDIR)/$(KBUILD_OUTPUT)/System.map $(DEPMOD_OPT) $(KERNELRELEASE) ; fi - - -clean: - $(MAKE) -C $(KERNELDIR) M=$(PWD) clean -endif diff --git a/trunk/ltt-modules/ltt-control.c b/trunk/ltt-modules/ltt-control.c deleted file mode 100644 index 45b44f0f..00000000 --- a/trunk/ltt-modules/ltt-control.c +++ /dev/null @@ -1,115 +0,0 @@ -/* ltt-control.c - * - * LTT control module over a netlink socket. - * - * Inspired from Relay Apps, by Tom Zanussi and iptables - * - * Copyright 2005 - - * Mathieu Desnoyers - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ltt-control.h" - - -#define LTTCTLM_BASE 0x10 -#define LTTCTLM_CONTROL (LTTCTLM_BASE + 1) /* LTT control message */ - -static struct sock *socket; - -void ltt_control_input(struct sock *sk, int len) -{ - struct sk_buff *skb; - struct nlmsghdr *nlh = NULL; - u8 *payload = NULL; - lttctl_peer_msg_t *msg; - int err; - - printk(KERN_ALERT "ltt-control ltt_control_input\n"); - - while ((skb = skb_dequeue(&sk->sk_receive_queue)) - != NULL) { - - nlh = (struct nlmsghdr *)skb->data; - - if(security_netlink_recv(skb)) { - netlink_ack(skb, nlh, EPERM); - kfree_skb(skb); - continue; - } - - /* process netlink message pointed by skb->data */ - err = EINVAL; - payload = NLMSG_DATA(nlh); - /* process netlink message with header pointed by - * nlh and payload pointed by payload - */ - if(nlh->nlmsg_len != sizeof(lttctl_peer_msg_t) + sizeof(struct nlmsghdr)) { - printk(KERN_ALERT "ltt-control bad message length\n"); - netlink_ack(skb, nlh, EINVAL); - kfree_skb(skb); - continue; - } - msg = (lttctl_peer_msg_t*)payload; - - switch(msg->op) { - case OP_CREATE: - err = ltt_control(LTT_CONTROL_CREATE_TRACE, msg->trace_name, - msg->args); - break; - case OP_DESTROY: - err = ltt_control(LTT_CONTROL_DESTROY_TRACE, msg->trace_name, - msg->args); - break; - case OP_START: - err = ltt_control(LTT_CONTROL_START, msg->trace_name, - msg->args); - break; - case OP_STOP: - err = ltt_control(LTT_CONTROL_STOP, msg->trace_name, - msg->args); - break; - default: - err = EBADRQC; - printk(KERN_INFO "ltt-control invalid operation\n"); - } - netlink_ack(skb, nlh, err); - kfree_skb(skb); - } -} - - -static int ltt_control_init(void) -{ - printk(KERN_ALERT "ltt-control init\n"); - - socket = netlink_kernel_create(NETLINK_LTT, 1, - ltt_control_input, THIS_MODULE); - if(socket == NULL) return -EPERM; - else return 0; -} - -static void ltt_control_exit(void) -{ - printk(KERN_ALERT "ltt-control exit\n"); - - sock_release(socket->sk_socket); -} - - -module_init(ltt_control_init) -module_exit(ltt_control_exit) - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mathieu Desnoyers"); -MODULE_DESCRIPTION("Linux Trace Toolkit Controller"); - diff --git a/trunk/ltt-modules/ltt-control.h b/trunk/ltt-modules/ltt-control.h deleted file mode 100644 index 430d5d12..00000000 --- a/trunk/ltt-modules/ltt-control.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _LTT_CONTROL_H -#define _LTT_CONTROL_H - - -//enum trace_mode { -// TRACE_NORMAL, -// TRACE_FLIGHT -//}; - -enum trace_op { - OP_CREATE, - OP_DESTROY, - OP_START, - OP_STOP, - OP_ALIGN, - OP_NONE -}; - -typedef struct lttctl_peer_msg { - char trace_name[NAME_MAX]; - enum trace_op op; - union ltt_control_args args; -} lttctl_peer_msg_t; - -#endif //_LTT_CONTROL_H - diff --git a/trunk/ltt-modules/ltt-statedump.c b/trunk/ltt-modules/ltt-statedump.c deleted file mode 100644 index d6c03217..00000000 --- a/trunk/ltt-modules/ltt-statedump.c +++ /dev/null @@ -1,352 +0,0 @@ -/* ltt-state-dump.c - * - * Lunix Trace Toolkit Kernel State Dump - * - * Copyright 2005 - - * Jean-Hugues Deschenes - * - * Changes: - * Eric Clement: add listing of network IP interface - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NB_PROC_CHUNK 20 - -#include -#include - -/* in modules.c */ -extern int ltt_enumerate_modules(void); - -static inline int ltt_enumerate_network_ip_interface(void) -{ - struct net_device *list; - struct in_device *in_dev = NULL; - struct in_ifaddr *ifa = NULL; - - read_lock(&dev_base_lock); - for(list=dev_base; list != NULL; list=list->next) { - - if(list->flags & IFF_UP) { - in_dev = in_dev_get(list); - - if(in_dev) { - for (ifa = in_dev->ifa_list; ifa != NULL; ifa = ifa->ifa_next) { - trace_statedump_enumerate_network_ip_interface(list->name, - ifa->ifa_address, - LTTNG_UP); - } - in_dev_put(in_dev); - } - } else { - trace_statedump_enumerate_network_ip_interface(list->name, - 0, - LTTNG_DOWN); - } - } - read_unlock(&dev_base_lock); - - return 0; -} - -static inline int ltt_enumerate_file_descriptors(void) -{ - struct task_struct * t = &init_task; - unsigned int i; - struct file * filp; - char *tmp = (char*)__get_free_page(GFP_KERNEL), *path; - struct fdtable *fdt; - - /* Enumerate active file descriptors */ - - do { - read_lock(&tasklist_lock); - if(t != &init_task) atomic_dec(&t->usage); - t = next_task(t); - atomic_inc(&t->usage); - read_unlock(&tasklist_lock); - - task_lock(t); - if (t->files) { - spin_lock(&t->files->file_lock); - fdt = files_fdtable(t->files); - for (i=0; i < fdt->max_fds; i++) { - filp = fcheck_files(t->files, i); - if (!filp) - continue; - path = d_path(filp->f_dentry, filp->f_vfsmnt, tmp, PAGE_SIZE); - - /* Make sure we give at least some info */ - if(IS_ERR(path)) - trace_statedump_enumerate_file_descriptors(filp->f_dentry->d_name.name, t->pid, i); - else - trace_statedump_enumerate_file_descriptors(path, t->pid, i); - } - spin_unlock(&t->files->file_lock); - } - task_unlock(t); - - } while( t != &init_task ); - - free_page((unsigned long)tmp); - - return 0; -} - -static inline int ltt_enumerate_vm_maps(void) -{ - struct mm_struct *mm; - struct task_struct * t = &init_task; - struct vm_area_struct * map; - unsigned long ino = 0; - - do { - read_lock(&tasklist_lock); - if(t != &init_task) atomic_dec(&t->usage); - t = next_task(t); - atomic_inc(&t->usage); - read_unlock(&tasklist_lock); - - /* get_task_mm does a task_lock... */ - - mm = get_task_mm(t); - - if (mm) - { - map = mm->mmap; - - if(map) - { - down_read(&mm->mmap_sem); - - while (map) { - if (map->vm_file) { - ino = map->vm_file->f_dentry->d_inode->i_ino; - } else { - ino = 0; - } - - trace_statedump_enumerate_vm_maps(t->pid, (void *)map->vm_start, (void *)map->vm_end, map->vm_flags, map->vm_pgoff << PAGE_SHIFT, ino); - map = map->vm_next; - } - - up_read(&mm->mmap_sem); - } - - mmput(mm); - } - - } while( t != &init_task ); - - return 0; -} - -#if defined( CONFIG_ARM ) -/* defined in arch/arm/kernel/irq.c because of dependency on statically-defined lock & irq_desc */ -int ltt_enumerate_interrupts(void); -#else -static inline int ltt_enumerate_interrupts(void) -{ - unsigned int i; - unsigned long flags = 0; - - /* needs irq_desc */ - - for(i = 0; i < NR_IRQS; i++) - { - struct irqaction * action; - - spin_lock_irqsave(&irq_desc[i].lock, flags); - - - for (action=irq_desc[i].action; action; action = action->next) - trace_statedump_enumerate_interrupts( - irq_desc[i].handler->typename, - action->name, - i ); - - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - - return 0; -} -#endif - -static inline int ltt_enumerate_process_states(void) -{ - struct task_struct * t = &init_task; - struct task_struct * p = t; - enum lttng_process_status status; - enum lttng_thread_type type; - enum lttng_execution_mode mode; - enum lttng_execution_submode submode; - - do { - mode = LTTNG_MODE_UNKNOWN; - submode = LTTNG_UNKNOWN; - - read_lock(&tasklist_lock); - if(t != &init_task) { - atomic_dec(&t->usage); - t = next_thread(t); - } - if(t == p) { - t = p = next_task(t); - } - atomic_inc(&t->usage); - read_unlock(&tasklist_lock); - - task_lock(t); - - if(t->exit_state == EXIT_ZOMBIE) - status = LTTNG_ZOMBIE; - else if(t->exit_state == EXIT_DEAD) - status = LTTNG_DEAD; - else if(t->state == TASK_RUNNING) - { - /* Is this a forked child that has not run yet? */ - if( list_empty(&t->run_list) ) - { - status = LTTNG_WAIT_FORK; - } - else - { - /* All tasks are considered as wait_cpu; the viewer will sort out if the task was relly running at this time. */ - status = LTTNG_WAIT_CPU; - } - } - else if(t->state & (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)) - { - /* Task is waiting for something to complete */ - status = LTTNG_WAIT; - } - else - status = LTTNG_UNNAMED; - - submode = LTTNG_NONE; - - - /* Verification of t->mm is to filter out kernel threads; - Viewer will further filter out if a user-space thread was in syscall mode or not */ - if(t->mm) - type = LTTNG_USER_THREAD; - else - type = LTTNG_KERNEL_THREAD; - - trace_statedump_enumerate_process_state(t->pid, t->parent->pid, t->comm, - type, mode, submode, status); - - task_unlock(t); - - } while( t != &init_task ); - - return 0; -} - -void ltt_statedump_work_func(void *sem) -{ - /* Our job is just to release the semaphore so - that we are sure that each CPU has been in syscall - mode before the end of ltt_statedump_thread */ - up((struct semaphore *)sem); -} - -static struct work_struct cpu_work[NR_CPUS]; - -int ltt_statedump_thread(void *data) -{ - struct semaphore work_sema4; - int cpu; - - printk("ltt_statedump_thread\n"); - - ltt_enumerate_process_states(); - - ltt_enumerate_file_descriptors(); - - ltt_enumerate_modules(); - - ltt_enumerate_vm_maps(); - - ltt_enumerate_interrupts(); - - ltt_enumerate_network_ip_interface(); - - /* Fire off a work queue on each CPU. Their sole purpose in life - * is to guarantee that each CPU has been in a state where is was in syscall - * mode (i.e. not in a trap, an IRQ or a soft IRQ) */ - sema_init(&work_sema4, 1 - num_online_cpus()); - - lock_cpu_hotplug(); - for_each_online_cpu(cpu) - { - INIT_WORK(&cpu_work[cpu], ltt_statedump_work_func, &work_sema4); - - schedule_delayed_work_on(cpu,&cpu_work[cpu],0); - } - unlock_cpu_hotplug(); - - /* Wait for all work queues to have completed */ - down(&work_sema4); - - /* Our work is done */ - printk("trace_statedump_statedump_end\n"); - trace_statedump_statedump_end(); - - do_exit(0); - - return 0; -} - -int ltt_statedump_start(struct ltt_trace_struct *trace) -{ - printk("ltt_statedump_start\n"); - - kthread_run( ltt_statedump_thread, - NULL, - "ltt_statedump"); - - return 0; -} - - -/* Dynamic facility. */ - -static int __init statedump_init(void) -{ - int ret; - printk(KERN_INFO "LTT : ltt-facility-statedump init\n"); - - ret = ltt_module_register(LTT_FUNCTION_STATEDUMP, - ltt_statedump_start,THIS_MODULE); - - return ret; -} - -static void __exit statedump_exit(void) -{ - ltt_module_unregister(LTT_FUNCTION_STATEDUMP); -} - -module_init(statedump_init) -module_exit(statedump_exit) - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jean-Hugues Deschenes"); -MODULE_DESCRIPTION("Linux Trace Toolkit Statedump"); -