All of lore.kernel.org
 help / color / mirror / Atom feed
* Detailed Stack Information Patch [2/3]
@ 2009-03-31 14:58 ` Stefani Seibold
  0 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-03-31 14:58 UTC (permalink / raw)
  To: linux-kernel, linux-mm; +Cc: Peter Zijlstra, Ingo Molnar, Joerg Engel

diff -u -N -r linux-2.6.29.orig/fs/proc/Makefile linux-2.6.29/fs/proc/Makefile
--- linux-2.6.29.orig/fs/proc/Makefile	2009-03-24 00:12:14.000000000 +0100
+++ linux-2.6.29/fs/proc/Makefile	2009-03-31 16:08:26.000000000 +0200
@@ -25,3 +25,4 @@
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
 proc-$(CONFIG_PRINTK)	+= kmsg.o
 proc-$(CONFIG_PROC_PAGE_MONITOR)	+= page.o
+proc-$(CONFIG_PROC_STACK_MONITOR) += stackmon.o
diff -u -N -r linux-2.6.29.orig/fs/proc/stackmon.c linux-2.6.29/fs/proc/stackmon.c
--- linux-2.6.29.orig/fs/proc/stackmon.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.29/fs/proc/stackmon.c	2009-03-31 16:08:26.000000000 +0200
@@ -0,0 +1,254 @@
+/*
+ * detailed stack monitoring
+ *
+ *	Copyright (C) 2009 Stefani Seibold for NSN
+ *	This Source is under GPL Licence
+ *
+ * enabled when CONFIG_PROC_STACK_MONITOR is set
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/seq_file.h>
+
+#define	PROC_STACKMON	"stackmon"
+
+#define	BUF_SIZE	1024
+
+static struct mutex		lock;
+
+static struct proc_dir_entry	*proc_ent;
+
+#ifdef CONFIG_STACK_GROWSUP
+static inline unsigned long get_top(struct vm_area_struct *vma,
+					unsigned long end)
+{
+	unsigned long	i;
+	struct page	*page;
+
+	for (i = vma->vm_end; i-PAGE_SIZE > end; i -= PAGE_SIZE) {
+
+		page = follow_page(vma, i-PAGE_SIZE, 0);
+
+		if ((!IS_ERR(page) == 0) || (page))
+			break;
+	}
+	return (i-end)/PAGE_SIZE;
+}
+#else
+static inline unsigned long get_top(struct vm_area_struct *vma,
+					unsigned long end)
+{
+	unsigned long	i;
+	struct page	*page;
+
+	for (i = vma->vm_start; i+PAGE_SIZE <= end; i += PAGE_SIZE) {
+
+		page = follow_page(vma, i, 0);
+
+		if ((!IS_ERR(page) == 0) || (page))
+			break;
+	}
+	return (end-i)/PAGE_SIZE;
+}
+#endif
+
+#ifdef CONFIG_STACK_GROWSUP
+#define STACK_PAGE(x)	(((x)+PAGE_SIZE-1)/PAGE_SIZE)
+#else
+#define STACK_PAGE(x)	(((x)-PAGE_SIZE-1)/PAGE_SIZE)
+#endif
+
+static inline int dump_usage(struct task_struct *t, char *buf)
+{
+	struct vm_area_struct	*vma;
+	struct mm_struct	*mm;
+
+	*buf = 0;
+
+	mm = get_task_mm(t);
+
+	if (mm) {
+		vma = find_vma(mm, t->stack_start);
+
+		if (vma) {
+			unsigned long	esp;
+			unsigned long	cur_stack;
+			unsigned long	real_stack;
+
+			esp = KSTK_ESP(t);
+
+#ifdef CONFIG_STACK_GROWSUP
+			cur_stack = esp-t->stack_start;
+			real_stack =
+				STACK_PAGE(esp)-STACK_PAGE(t->stack_start)+1;
+#else
+			cur_stack = t->stack_start-esp;
+			real_stack =
+				STACK_PAGE(t->stack_start)-STACK_PAGE(esp)+1;
+#endif
+			snprintf(
+				buf,
+				BUF_SIZE,
+				" %7lu %7lu %7lu  %08lx-%08lx pid:%5d "
+				"tid:%5d %s\n",
+				cur_stack,
+				real_stack,
+				(real_stack+get_top(vma, esp)),
+				vma->vm_start,
+				vma->vm_end,
+				t->tgid,
+				t->pid,
+				t->comm
+			);
+		}
+		mmput(mm);
+	}
+	return 0;
+}
+
+static void *stackmon_find(loff_t pos, char *buf)
+{
+	struct task_struct *g;
+	struct task_struct *t;
+
+	loff_t off = 0;
+
+	read_lock(&tasklist_lock);
+
+	do_each_thread(g, t) {
+		if (pos == off++)
+			goto found;
+	} while_each_thread(g, t);
+
+	read_unlock(&tasklist_lock);
+	return 0;
+found:
+	task_lock(t);
+	dump_usage(t, buf);
+	task_unlock(t);
+	read_unlock(&tasklist_lock);
+	return buf;
+}
+
+static void *stackmon_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	return stackmon_find(*pos, s->private);
+}
+
+
+static void *stackmon_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	++*pos;
+
+	return stackmon_find(*pos, s->private);
+}
+
+static int stackmon_seq_show(struct seq_file *s, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		return seq_puts(s,
+			"   bytes   pages maxpages vm_start vm_end   "
+			"processid threadid  name\n");
+	}
+
+	return seq_puts(s, v);
+}
+
+static void stackmon_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static const struct seq_operations stackmon_seq_ops = {
+	.start	= stackmon_seq_start,
+	.next	= stackmon_seq_next,
+	.stop	= stackmon_seq_stop,
+	.show	= stackmon_seq_show
+};
+
+static int stackmon_open(struct inode *inode, struct file *file)
+{
+	int	ret;
+	char	*buffer;
+	struct seq_file *s;
+
+	ret = -ENOMEM;
+
+	buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
+	if (!buffer)
+		goto out;
+
+	ret = seq_open(file, &stackmon_seq_ops);
+	if (ret)
+		goto out_kfree;
+
+	s = file->private_data;
+	s->private = buffer;
+
+out:
+	return ret;
+
+out_kfree:
+	kfree(buffer);
+	return ret;
+}
+
+static const struct file_operations stackmon_file_ops = {
+	.owner		= THIS_MODULE,
+	.open		= stackmon_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
+
+static int __init stackmon_init(void)
+{
+	int ret = 0;
+
+	mutex_init(&lock);
+
+	proc_ent = create_proc_entry(PROC_STACKMON, 0440, NULL);
+
+	if (proc_ent == NULL)
+		goto exit;
+
+	proc_ent->owner = THIS_MODULE;
+	proc_ent->data = NULL;
+	proc_ent->proc_fops = &stackmon_file_ops;
+
+	return ret;
+
+exit:
+	return -ENOMEM;
+}
+
+static void __exit stackmon_exit(void)
+{
+	mutex_lock(&lock);
+	remove_proc_entry(PROC_STACKMON, NULL);
+	mutex_unlock(&lock);
+}
+
+module_init(stackmon_init);
+module_exit(stackmon_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");
+MODULE_DESCRIPTION("detailed stack monitoring");
+
diff -u -N -r linux-2.6.29.orig/init/Kconfig linux-2.6.29/init/Kconfig
--- linux-2.6.29.orig/init/Kconfig	2009-03-31 16:08:11.000000000 +0200
+++ linux-2.6.29/init/Kconfig	2009-03-31 16:08:26.000000000 +0200
@@ -964,6 +964,16 @@
 	  Disabling these interfaces will reduce the size of the kernel by
 	  approximately 1kb.
 
+config PROC_STACK_MONITOR
+ 	default y
+	depends on PROC_STACK
+	bool "Enable /proc/stackmon detailed stack monitoring"
+ 	help
+	  This enables detailed monitoring of process and thread stack
+	  utilization via the /proc/stackmon interface.
+	  Disabling these interfaces will reduce the size of the kernel by
+	  approximately 2kb.
+
 endmenu		# General setup
 
 config HAVE_GENERIC_DMA_COHERENT



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Detailed Stack Information Patch [2/3]
@ 2009-03-31 14:58 ` Stefani Seibold
  0 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-03-31 14:58 UTC (permalink / raw)
  To: linux-kernel, linux-mm; +Cc: Peter Zijlstra, Ingo Molnar, Joerg Engel

diff -u -N -r linux-2.6.29.orig/fs/proc/Makefile linux-2.6.29/fs/proc/Makefile
--- linux-2.6.29.orig/fs/proc/Makefile	2009-03-24 00:12:14.000000000 +0100
+++ linux-2.6.29/fs/proc/Makefile	2009-03-31 16:08:26.000000000 +0200
@@ -25,3 +25,4 @@
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
 proc-$(CONFIG_PRINTK)	+= kmsg.o
 proc-$(CONFIG_PROC_PAGE_MONITOR)	+= page.o
+proc-$(CONFIG_PROC_STACK_MONITOR) += stackmon.o
diff -u -N -r linux-2.6.29.orig/fs/proc/stackmon.c linux-2.6.29/fs/proc/stackmon.c
--- linux-2.6.29.orig/fs/proc/stackmon.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.29/fs/proc/stackmon.c	2009-03-31 16:08:26.000000000 +0200
@@ -0,0 +1,254 @@
+/*
+ * detailed stack monitoring
+ *
+ *	Copyright (C) 2009 Stefani Seibold for NSN
+ *	This Source is under GPL Licence
+ *
+ * enabled when CONFIG_PROC_STACK_MONITOR is set
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/seq_file.h>
+
+#define	PROC_STACKMON	"stackmon"
+
+#define	BUF_SIZE	1024
+
+static struct mutex		lock;
+
+static struct proc_dir_entry	*proc_ent;
+
+#ifdef CONFIG_STACK_GROWSUP
+static inline unsigned long get_top(struct vm_area_struct *vma,
+					unsigned long end)
+{
+	unsigned long	i;
+	struct page	*page;
+
+	for (i = vma->vm_end; i-PAGE_SIZE > end; i -= PAGE_SIZE) {
+
+		page = follow_page(vma, i-PAGE_SIZE, 0);
+
+		if ((!IS_ERR(page) == 0) || (page))
+			break;
+	}
+	return (i-end)/PAGE_SIZE;
+}
+#else
+static inline unsigned long get_top(struct vm_area_struct *vma,
+					unsigned long end)
+{
+	unsigned long	i;
+	struct page	*page;
+
+	for (i = vma->vm_start; i+PAGE_SIZE <= end; i += PAGE_SIZE) {
+
+		page = follow_page(vma, i, 0);
+
+		if ((!IS_ERR(page) == 0) || (page))
+			break;
+	}
+	return (end-i)/PAGE_SIZE;
+}
+#endif
+
+#ifdef CONFIG_STACK_GROWSUP
+#define STACK_PAGE(x)	(((x)+PAGE_SIZE-1)/PAGE_SIZE)
+#else
+#define STACK_PAGE(x)	(((x)-PAGE_SIZE-1)/PAGE_SIZE)
+#endif
+
+static inline int dump_usage(struct task_struct *t, char *buf)
+{
+	struct vm_area_struct	*vma;
+	struct mm_struct	*mm;
+
+	*buf = 0;
+
+	mm = get_task_mm(t);
+
+	if (mm) {
+		vma = find_vma(mm, t->stack_start);
+
+		if (vma) {
+			unsigned long	esp;
+			unsigned long	cur_stack;
+			unsigned long	real_stack;
+
+			esp = KSTK_ESP(t);
+
+#ifdef CONFIG_STACK_GROWSUP
+			cur_stack = esp-t->stack_start;
+			real_stack =
+				STACK_PAGE(esp)-STACK_PAGE(t->stack_start)+1;
+#else
+			cur_stack = t->stack_start-esp;
+			real_stack =
+				STACK_PAGE(t->stack_start)-STACK_PAGE(esp)+1;
+#endif
+			snprintf(
+				buf,
+				BUF_SIZE,
+				" %7lu %7lu %7lu  %08lx-%08lx pid:%5d "
+				"tid:%5d %s\n",
+				cur_stack,
+				real_stack,
+				(real_stack+get_top(vma, esp)),
+				vma->vm_start,
+				vma->vm_end,
+				t->tgid,
+				t->pid,
+				t->comm
+			);
+		}
+		mmput(mm);
+	}
+	return 0;
+}
+
+static void *stackmon_find(loff_t pos, char *buf)
+{
+	struct task_struct *g;
+	struct task_struct *t;
+
+	loff_t off = 0;
+
+	read_lock(&tasklist_lock);
+
+	do_each_thread(g, t) {
+		if (pos == off++)
+			goto found;
+	} while_each_thread(g, t);
+
+	read_unlock(&tasklist_lock);
+	return 0;
+found:
+	task_lock(t);
+	dump_usage(t, buf);
+	task_unlock(t);
+	read_unlock(&tasklist_lock);
+	return buf;
+}
+
+static void *stackmon_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	return stackmon_find(*pos, s->private);
+}
+
+
+static void *stackmon_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	++*pos;
+
+	return stackmon_find(*pos, s->private);
+}
+
+static int stackmon_seq_show(struct seq_file *s, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		return seq_puts(s,
+			"   bytes   pages maxpages vm_start vm_end   "
+			"processid threadid  name\n");
+	}
+
+	return seq_puts(s, v);
+}
+
+static void stackmon_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static const struct seq_operations stackmon_seq_ops = {
+	.start	= stackmon_seq_start,
+	.next	= stackmon_seq_next,
+	.stop	= stackmon_seq_stop,
+	.show	= stackmon_seq_show
+};
+
+static int stackmon_open(struct inode *inode, struct file *file)
+{
+	int	ret;
+	char	*buffer;
+	struct seq_file *s;
+
+	ret = -ENOMEM;
+
+	buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
+	if (!buffer)
+		goto out;
+
+	ret = seq_open(file, &stackmon_seq_ops);
+	if (ret)
+		goto out_kfree;
+
+	s = file->private_data;
+	s->private = buffer;
+
+out:
+	return ret;
+
+out_kfree:
+	kfree(buffer);
+	return ret;
+}
+
+static const struct file_operations stackmon_file_ops = {
+	.owner		= THIS_MODULE,
+	.open		= stackmon_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
+
+static int __init stackmon_init(void)
+{
+	int ret = 0;
+
+	mutex_init(&lock);
+
+	proc_ent = create_proc_entry(PROC_STACKMON, 0440, NULL);
+
+	if (proc_ent == NULL)
+		goto exit;
+
+	proc_ent->owner = THIS_MODULE;
+	proc_ent->data = NULL;
+	proc_ent->proc_fops = &stackmon_file_ops;
+
+	return ret;
+
+exit:
+	return -ENOMEM;
+}
+
+static void __exit stackmon_exit(void)
+{
+	mutex_lock(&lock);
+	remove_proc_entry(PROC_STACKMON, NULL);
+	mutex_unlock(&lock);
+}
+
+module_init(stackmon_init);
+module_exit(stackmon_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");
+MODULE_DESCRIPTION("detailed stack monitoring");
+
diff -u -N -r linux-2.6.29.orig/init/Kconfig linux-2.6.29/init/Kconfig
--- linux-2.6.29.orig/init/Kconfig	2009-03-31 16:08:11.000000000 +0200
+++ linux-2.6.29/init/Kconfig	2009-03-31 16:08:26.000000000 +0200
@@ -964,6 +964,16 @@
 	  Disabling these interfaces will reduce the size of the kernel by
 	  approximately 1kb.
 
+config PROC_STACK_MONITOR
+ 	default y
+	depends on PROC_STACK
+	bool "Enable /proc/stackmon detailed stack monitoring"
+ 	help
+	  This enables detailed monitoring of process and thread stack
+	  utilization via the /proc/stackmon interface.
+	  Disabling these interfaces will reduce the size of the kernel by
+	  approximately 2kb.
+
 endmenu		# General setup
 
 config HAVE_GENERIC_DMA_COHERENT


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
  2009-03-31 14:58 ` Stefani Seibold
@ 2009-04-01 19:36   ` Ingo Molnar
  -1 siblings, 0 replies; 13+ messages in thread
From: Ingo Molnar @ 2009-04-01 19:36 UTC (permalink / raw)
  To: Stefani Seibold, Andrew Morton
  Cc: linux-kernel, linux-mm, Peter Zijlstra, Joerg Engel


* Stefani Seibold <stefani@seibold.net> wrote:

> +config PROC_STACK_MONITOR
> + 	default y
> +	depends on PROC_STACK
> +	bool "Enable /proc/stackmon detailed stack monitoring"
> + 	help
> +	  This enables detailed monitoring of process and thread stack
> +	  utilization via the /proc/stackmon interface.
> +	  Disabling these interfaces will reduce the size of the kernel by
> +	  approximately 2kb.

Hm, i'm not convinced about this one. Stupid question: what's wrong 
with ulimit -s?

Also, if for some reason you dont want to (or cannot) enforce a 
system-wide stack size ulimit, or it has some limitation that makes 
it impractical for you - if we add what i suggested to the 
/proc/*/maps files, your user-space watchdog daemon could scan those 
periodically and report any excesses and zap the culprit ... right?

	Ingo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
@ 2009-04-01 19:36   ` Ingo Molnar
  0 siblings, 0 replies; 13+ messages in thread
From: Ingo Molnar @ 2009-04-01 19:36 UTC (permalink / raw)
  To: Stefani Seibold, Andrew Morton
  Cc: linux-kernel, linux-mm, Peter Zijlstra, Joerg Engel


* Stefani Seibold <stefani@seibold.net> wrote:

> +config PROC_STACK_MONITOR
> + 	default y
> +	depends on PROC_STACK
> +	bool "Enable /proc/stackmon detailed stack monitoring"
> + 	help
> +	  This enables detailed monitoring of process and thread stack
> +	  utilization via the /proc/stackmon interface.
> +	  Disabling these interfaces will reduce the size of the kernel by
> +	  approximately 2kb.

Hm, i'm not convinced about this one. Stupid question: what's wrong 
with ulimit -s?

Also, if for some reason you dont want to (or cannot) enforce a 
system-wide stack size ulimit, or it has some limitation that makes 
it impractical for you - if we add what i suggested to the 
/proc/*/maps files, your user-space watchdog daemon could scan those 
periodically and report any excesses and zap the culprit ... right?

	Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
  2009-04-01 19:36   ` Ingo Molnar
@ 2009-04-02 21:25     ` Stefani Seibold
  -1 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-04-02 21:25 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Andrew Morton, linux-kernel, linux-mm, Peter Zijlstra, Joerg Engel

Am Mittwoch, den 01.04.2009, 21:36 +0200 schrieb Ingo Molnar:
> * Stefani Seibold <stefani@seibold.net> wrote:
> 
> > +config PROC_STACK_MONITOR
> > + 	default y
> > +	depends on PROC_STACK
> > +	bool "Enable /proc/stackmon detailed stack monitoring"
> > + 	help
> > +	  This enables detailed monitoring of process and thread stack
> > +	  utilization via the /proc/stackmon interface.
> > +	  Disabling these interfaces will reduce the size of the kernel by
> > +	  approximately 2kb.
> 
> Hm, i'm not convinced about this one. Stupid question: what's wrong 
> with ulimit -s?
> 

To tell a long story short, you are right. After a quick investigation
of the glibc 2.9 library i figure out that this is also the default
stack size of a thread started with pthread_create().

> Also, if for some reason you dont want to (or cannot) enforce a 
> system-wide stack size ulimit, or it has some limitation that makes 
> it impractical for you - if we add what i suggested to the 
> /proc/*/maps files, your user-space watchdog daemon could scan those 
> periodically and report any excesses and zap the culprit ... right?

I think a user space daemon will be the a good way if the /proc/*/maps
or /proc/*/stack will provide the following information:

- start address of the stack
- current address of the stack pointer
- highest used address in the stack

> 
> 	Ingo

Stefani



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
@ 2009-04-02 21:25     ` Stefani Seibold
  0 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-04-02 21:25 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Andrew Morton, linux-kernel, linux-mm, Peter Zijlstra, Joerg Engel

Am Mittwoch, den 01.04.2009, 21:36 +0200 schrieb Ingo Molnar:
> * Stefani Seibold <stefani@seibold.net> wrote:
> 
> > +config PROC_STACK_MONITOR
> > + 	default y
> > +	depends on PROC_STACK
> > +	bool "Enable /proc/stackmon detailed stack monitoring"
> > + 	help
> > +	  This enables detailed monitoring of process and thread stack
> > +	  utilization via the /proc/stackmon interface.
> > +	  Disabling these interfaces will reduce the size of the kernel by
> > +	  approximately 2kb.
> 
> Hm, i'm not convinced about this one. Stupid question: what's wrong 
> with ulimit -s?
> 

To tell a long story short, you are right. After a quick investigation
of the glibc 2.9 library i figure out that this is also the default
stack size of a thread started with pthread_create().

> Also, if for some reason you dont want to (or cannot) enforce a 
> system-wide stack size ulimit, or it has some limitation that makes 
> it impractical for you - if we add what i suggested to the 
> /proc/*/maps files, your user-space watchdog daemon could scan those 
> periodically and report any excesses and zap the culprit ... right?

I think a user space daemon will be the a good way if the /proc/*/maps
or /proc/*/stack will provide the following information:

- start address of the stack
- current address of the stack pointer
- highest used address in the stack

> 
> 	Ingo

Stefani


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
  2009-04-02 21:25     ` Stefani Seibold
@ 2009-04-03  7:32       ` Mikael Pettersson
  -1 siblings, 0 replies; 13+ messages in thread
From: Mikael Pettersson @ 2009-04-03  7:32 UTC (permalink / raw)
  To: Stefani Seibold
  Cc: Ingo Molnar, Andrew Morton, linux-kernel, linux-mm,
	Peter Zijlstra, Joerg Engel

Stefani Seibold writes:
 > I think a user space daemon will be the a good way if the /proc/*/maps
 > or /proc/*/stack will provide the following information:
 > 
 > - start address of the stack
 > - current address of the stack pointer
 > - highest used address in the stack

You're assuming
1. a thread has exactly one stack
2. the stack is a single unbroken area
3. the kernel knows the location of this area

None of these assumptions are necessarily valid, esp. in
the presence of virtualizers, managed runtimes, or mixed
interpreted/JIT language implementations.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
@ 2009-04-03  7:32       ` Mikael Pettersson
  0 siblings, 0 replies; 13+ messages in thread
From: Mikael Pettersson @ 2009-04-03  7:32 UTC (permalink / raw)
  To: Stefani Seibold
  Cc: Ingo Molnar, Andrew Morton, linux-kernel, linux-mm,
	Peter Zijlstra, Joerg Engel

Stefani Seibold writes:
 > I think a user space daemon will be the a good way if the /proc/*/maps
 > or /proc/*/stack will provide the following information:
 > 
 > - start address of the stack
 > - current address of the stack pointer
 > - highest used address in the stack

You're assuming
1. a thread has exactly one stack
2. the stack is a single unbroken area
3. the kernel knows the location of this area

None of these assumptions are necessarily valid, esp. in
the presence of virtualizers, managed runtimes, or mixed
interpreted/JIT language implementations.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
  2009-04-03  7:32       ` Mikael Pettersson
@ 2009-04-03  8:01         ` Stefani Seibold
  -1 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-04-03  8:01 UTC (permalink / raw)
  To: Mikael Pettersson
  Cc: Ingo Molnar, Andrew Morton, linux-kernel, linux-mm,
	Peter Zijlstra, Joerg Engel

Am Freitag, den 03.04.2009, 09:32 +0200 schrieb Mikael Pettersson:
> Stefani Seibold writes:
>  > I think a user space daemon will be the a good way if the /proc/*/maps
>  > or /proc/*/stack will provide the following information:
>  > 
>  > - start address of the stack
>  > - current address of the stack pointer
>  > - highest used address in the stack
> 
> You're assuming
> 1. a thread has exactly one stack
> 2. the stack is a single unbroken area
> 3. the kernel knows the location of this area
> 
> None of these assumptions are necessarily valid, esp. in
> the presence of virtualizers, managed runtimes, or mixed
> interpreted/JIT language implementations.

We are talking about the kernel view. And from this point a thread has
only one stack and it is a single mapped continuous area. There are only
one exception and that is the sigaltstack().



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
@ 2009-04-03  8:01         ` Stefani Seibold
  0 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-04-03  8:01 UTC (permalink / raw)
  To: Mikael Pettersson
  Cc: Ingo Molnar, Andrew Morton, linux-kernel, linux-mm,
	Peter Zijlstra, Joerg Engel

Am Freitag, den 03.04.2009, 09:32 +0200 schrieb Mikael Pettersson:
> Stefani Seibold writes:
>  > I think a user space daemon will be the a good way if the /proc/*/maps
>  > or /proc/*/stack will provide the following information:
>  > 
>  > - start address of the stack
>  > - current address of the stack pointer
>  > - highest used address in the stack
> 
> You're assuming
> 1. a thread has exactly one stack
> 2. the stack is a single unbroken area
> 3. the kernel knows the location of this area
> 
> None of these assumptions are necessarily valid, esp. in
> the presence of virtualizers, managed runtimes, or mixed
> interpreted/JIT language implementations.

We are talking about the kernel view. And from this point a thread has
only one stack and it is a single mapped continuous area. There are only
one exception and that is the sigaltstack().


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
  2009-04-03  8:01         ` Stefani Seibold
@ 2009-04-03  8:54           ` Mikael Pettersson
  -1 siblings, 0 replies; 13+ messages in thread
From: Mikael Pettersson @ 2009-04-03  8:54 UTC (permalink / raw)
  To: Stefani Seibold
  Cc: Mikael Pettersson, Ingo Molnar, Andrew Morton, linux-kernel,
	linux-mm, Peter Zijlstra, Joerg Engel

Stefani Seibold writes:
 > Am Freitag, den 03.04.2009, 09:32 +0200 schrieb Mikael Pettersson:
 > > Stefani Seibold writes:
 > >  > I think a user space daemon will be the a good way if the /proc/*/maps
 > >  > or /proc/*/stack will provide the following information:
 > >  > 
 > >  > - start address of the stack
 > >  > - current address of the stack pointer
 > >  > - highest used address in the stack
 > > 
 > > You're assuming
 > > 1. a thread has exactly one stack
 > > 2. the stack is a single unbroken area
 > > 3. the kernel knows the location of this area
 > > 
 > > None of these assumptions are necessarily valid, esp. in
 > > the presence of virtualizers, managed runtimes, or mixed
 > > interpreted/JIT language implementations.
 > 
 > We are talking about the kernel view. And from this point a thread has
 > only one stack and it is a single mapped continuous area. There are only
 > one exception and that is the sigaltstack().

So you're proposing to have the kernel export data which,
while accurate from the kernel's limited view, may be
arbitrarily inaccurate for the user-space process in question?

Also I'm not sure you even need a kernel extension for the
optimistic case of a single simple stack. ptrace to get stack
pointer then scan /proc/$tid/maps to identify the corresponding
mapping should give the same information, no?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Detailed Stack Information Patch [2/3]
@ 2009-04-03  8:54           ` Mikael Pettersson
  0 siblings, 0 replies; 13+ messages in thread
From: Mikael Pettersson @ 2009-04-03  8:54 UTC (permalink / raw)
  To: Stefani Seibold
  Cc: Mikael Pettersson, Ingo Molnar, Andrew Morton, linux-kernel,
	linux-mm, Peter Zijlstra, Joerg Engel

Stefani Seibold writes:
 > Am Freitag, den 03.04.2009, 09:32 +0200 schrieb Mikael Pettersson:
 > > Stefani Seibold writes:
 > >  > I think a user space daemon will be the a good way if the /proc/*/maps
 > >  > or /proc/*/stack will provide the following information:
 > >  > 
 > >  > - start address of the stack
 > >  > - current address of the stack pointer
 > >  > - highest used address in the stack
 > > 
 > > You're assuming
 > > 1. a thread has exactly one stack
 > > 2. the stack is a single unbroken area
 > > 3. the kernel knows the location of this area
 > > 
 > > None of these assumptions are necessarily valid, esp. in
 > > the presence of virtualizers, managed runtimes, or mixed
 > > interpreted/JIT language implementations.
 > 
 > We are talking about the kernel view. And from this point a thread has
 > only one stack and it is a single mapped continuous area. There are only
 > one exception and that is the sigaltstack().

So you're proposing to have the kernel export data which,
while accurate from the kernel's limited view, may be
arbitrarily inaccurate for the user-space process in question?

Also I'm not sure you even need a kernel extension for the
optimistic case of a single simple stack. ptrace to get stack
pointer then scan /proc/$tid/maps to identify the corresponding
mapping should give the same information, no?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Detailed Stack Information Patch [2/3]
@ 2009-01-20 10:16 Stefani Seibold
  0 siblings, 0 replies; 13+ messages in thread
From: Stefani Seibold @ 2009-01-20 10:16 UTC (permalink / raw)
  To: linux-kernel

diff -u -N -r linux-2.6.28.1.orig/fs/proc/Makefile linux-2.6.28.1/fs/proc/Makefile
--- linux-2.6.28.1.orig/fs/proc/Makefile	2009-01-18 19:45:37.000000000 +0100
+++ linux-2.6.28.1/fs/proc/Makefile	2009-01-20 09:14:11.000000000 +0100
@@ -25,3 +25,4 @@
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
 proc-$(CONFIG_PRINTK)	+= kmsg.o
 proc-$(CONFIG_PROC_PAGE_MONITOR)	+= page.o
+proc-$(CONFIG_PROC_STACK_MONITOR) += stackmon.o
diff -u -N -r linux-2.6.28.1.orig/fs/proc/stackmon.c linux-2.6.28.1/fs/proc/stackmon.c
--- linux-2.6.28.1.orig/fs/proc/stackmon.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.28.1/fs/proc/stackmon.c	2009-01-20 09:13:19.000000000 +0100
@@ -0,0 +1,254 @@
+/*
+ * detailed stack monitoring
+ *
+ *	Copyright (C) 2009 Stefani Seibold for NSN
+ *	This Source is under GPL Licence
+ *
+ * enabled when CONFIG_PROC_STACK_MONITOR is set
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/seq_file.h>
+
+#define	PROC_STACKMON	"stackmon"
+
+#define	BUF_SIZE	1024
+
+static struct mutex		lock;
+
+static struct proc_dir_entry	*proc_ent;
+
+#ifdef CONFIG_STACK_GROWSUP
+static inline unsigned long get_top(struct vm_area_struct *vma,
+					unsigned long end)
+{
+	unsigned long	i;
+	struct page	*page;
+
+	for (i = vma->vm_end; i-PAGE_SIZE > end; i -= PAGE_SIZE) {
+
+		page = follow_page(vma, i-PAGE_SIZE, 0);
+
+		if ((!IS_ERR(page) == 0) || (page))
+			break;
+	}
+	return (i-end)/PAGE_SIZE;
+}
+#else
+static inline unsigned long get_top(struct vm_area_struct *vma,
+					unsigned long end)
+{
+	unsigned long	i;
+	struct page	*page;
+
+	for (i = vma->vm_start; i+PAGE_SIZE <= end; i += PAGE_SIZE) {
+
+		page = follow_page(vma, i, 0);
+
+		if ((!IS_ERR(page) == 0) || (page))
+			break;
+	}
+	return (end-i)/PAGE_SIZE;
+}
+#endif
+
+#ifdef CONFIG_STACK_GROWSUP
+#define STACK_PAGE(x)	(((x)+PAGE_SIZE-1)/PAGE_SIZE)
+#else
+#define STACK_PAGE(x)	(((x)-PAGE_SIZE-1)/PAGE_SIZE)
+#endif
+
+static inline int dump_usage(struct task_struct *t, char *buf)
+{
+	struct vm_area_struct	*vma;
+	struct mm_struct	*mm;
+
+	*buf = 0;
+
+	mm = get_task_mm(t);
+
+	if (mm) {
+		vma = find_vma(mm, t->stack_start);
+
+		if (vma) {
+			unsigned long	esp;
+			unsigned long	cur_stack;
+			unsigned long	real_stack;
+
+			esp = KSTK_ESP(t);
+
+#ifdef CONFIG_STACK_GROWSUP
+			cur_stack = esp-t->stack_start;
+			real_stack =
+				STACK_PAGE(esp)-STACK_PAGE(t->stack_start)+1;
+#else
+			cur_stack = t->stack_start-esp;
+			real_stack =
+				STACK_PAGE(t->stack_start)-STACK_PAGE(esp)+1;
+#endif
+			snprintf(
+				buf,
+				BUF_SIZE,
+				" %7lu %7lu %7lu  %08lx-%08lx pid:%5d "
+				"tid:%5d %s\n",
+				cur_stack,
+				real_stack,
+				(real_stack+get_top(vma, esp)),
+				vma->vm_start,
+				vma->vm_end,
+				t->tgid,
+				t->pid,
+				t->comm
+			);
+		}
+		mmput(mm);
+	}
+	return 0;
+}
+
+static void *stackmon_find(loff_t pos, char *buf)
+{
+	struct task_struct *g;
+	struct task_struct *t;
+
+	loff_t off = 0;
+
+	read_lock(&tasklist_lock);
+
+	do_each_thread(g, t) {
+		if (pos == off++)
+			goto found;
+	} while_each_thread(g, t);
+
+	read_unlock(&tasklist_lock);
+	return 0;
+found:
+	task_lock(t);
+	dump_usage(t, buf);
+	task_unlock(t);
+	read_unlock(&tasklist_lock);
+	return buf;
+}
+
+static void *stackmon_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	return stackmon_find(*pos, s->private);
+}
+
+
+static void *stackmon_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	++*pos;
+
+	return stackmon_find(*pos, s->private);
+}
+
+static int stackmon_seq_show(struct seq_file *s, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		return seq_puts(s,
+			"   bytes   pages maxpages vm_start vm_end   "
+			"processid threadid  name\n");
+	}
+
+	return seq_puts(s, v);
+}
+
+static void stackmon_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static const struct seq_operations stackmon_seq_ops = {
+	.start	= stackmon_seq_start,
+	.next	= stackmon_seq_next,
+	.stop	= stackmon_seq_stop,
+	.show	= stackmon_seq_show
+};
+
+static int stackmon_open(struct inode *inode, struct file *file)
+{
+	int	ret;
+	char	*buffer;
+	struct seq_file *s;
+
+	ret = -ENOMEM;
+
+	buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
+	if (!buffer)
+		goto out;
+
+	ret = seq_open(file, &stackmon_seq_ops);
+	if (ret)
+		goto out_kfree;
+
+	s = file->private_data;
+	s->private = buffer;
+
+out:
+	return ret;
+
+out_kfree:
+	kfree(buffer);
+	return ret;
+}
+
+static const struct file_operations stackmon_file_ops = {
+	.owner		= THIS_MODULE,
+	.open		= stackmon_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
+
+static int __init stackmon_init(void)
+{
+	int ret = 0;
+
+	mutex_init(&lock);
+
+	proc_ent = create_proc_entry(PROC_STACKMON, 0440, NULL);
+
+	if (proc_ent == NULL)
+		goto exit;
+
+	proc_ent->owner = THIS_MODULE;
+	proc_ent->data = NULL;
+	proc_ent->proc_fops = &stackmon_file_ops;
+
+	return ret;
+
+exit:
+	return -ENOMEM;
+}
+
+static void __exit stackmon_exit(void)
+{
+	mutex_lock(&lock);
+	remove_proc_entry(PROC_STACKMON, NULL);
+	mutex_unlock(&lock);
+}
+
+module_init(stackmon_init);
+module_exit(stackmon_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");
+MODULE_DESCRIPTION("detailed stack monitoring");
+
diff -u -N -r linux-2.6.28.1.orig/init/Kconfig linux-2.6.28.1/init/Kconfig
--- linux-2.6.28.1.orig/init/Kconfig	2009-01-20 09:12:43.000000000 +0100
+++ linux-2.6.28.1/init/Kconfig	2009-01-20 09:13:19.000000000 +0100
@@ -826,6 +826,16 @@
 	  Disabling these interfaces will reduce the size of the kernel by
 	  approximately 1kb.
 
+config PROC_STACK_MONITOR
+ 	default y
+	depends on PROC_STACK
+	bool "Enable /proc/stackmon detailed stack monitoring"
+ 	help
+	  This enables detailed monitoring of process and thread stack
+	  utilization via the /proc/stackmon interface.
+	  Disabling these interfaces will reduce the size of the kernel by
+	  approximately 2kb.
+
 endmenu		# General setup
 
 config HAVE_GENERIC_DMA_COHERENT



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-04-03  8:55 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-31 14:58 Detailed Stack Information Patch [2/3] Stefani Seibold
2009-03-31 14:58 ` Stefani Seibold
2009-04-01 19:36 ` Ingo Molnar
2009-04-01 19:36   ` Ingo Molnar
2009-04-02 21:25   ` Stefani Seibold
2009-04-02 21:25     ` Stefani Seibold
2009-04-03  7:32     ` Mikael Pettersson
2009-04-03  7:32       ` Mikael Pettersson
2009-04-03  8:01       ` Stefani Seibold
2009-04-03  8:01         ` Stefani Seibold
2009-04-03  8:54         ` Mikael Pettersson
2009-04-03  8:54           ` Mikael Pettersson
  -- strict thread matches above, loose matches on Subject: below --
2009-01-20 10:16 Stefani Seibold

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.