From: Frank Sorenson <frank@tuxrocks.com>
To: ajwade@cpe001346162bf9-cm0011ae8cd564.cpe.net.cable.rogers.com
Cc: Denis Vlasenko <vda@ilport.com.ua>,
"linux-os (Dick Johnson)" <linux-os@analogic.com>,
Linux kernel <linux-kernel@vger.kernel.org>
Subject: Re: 4k stacks
Date: Tue, 27 Dec 2005 14:12:03 -0700 [thread overview]
Message-ID: <43B1AE23.4020105@tuxrocks.com> (raw)
In-Reply-To: <200512260340.55037.ajwade@cpe001346162bf9-cm0011ae8cd564.cpe.net.cable.rogers.com>
[-- Attachment #1: Type: text/plain, Size: 1588 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Andrew James Wade wrote:
> I've modified stack.c to handle 4k stacks. It can also provide information
> for 8k stacks (fwiw) by changing STACK_GRANULARITY.
>
> It found one stack with only 756 bytes left. I hope it's just due to a
> greedy boot-time function as I'm not running anything particularly exotic.
> (CIFS & Reiser4).
Yes, it does appear to be a boot-time function. It eventually becomes
PID 1, and the stack usage shrinks considerably.
Here is a different approach that uses a kernel module, rather than
/dev/mem. This module will display current stack usage for each PID, as
well as the maximum usage if the kernel has the stack-poison patch.
Also, the current call trace for each PID can be displayed if loaded
with "verbose=1".
for example:
1: init - free stack now: 3640, at max usage: 740
2: ksoftirqd/0 - free stack now: 3880, at max usage: 3788
3: watchdog/0 - free stack now: 3828, at max usage: 3736
4: events/0 - free stack now: 3784, at max usage: 3012
...
Disclaimer: This seems to work for me, but I'm not a very experienced
kernel hacker, so if it breaks, take care that you don't get hurt.
Comments and fixes are welcome.
Thanks,
Frank
- --
Frank Sorenson - KD7TZK
Systems Manager, Computer Science Department
Brigham Young University
frank@tuxrocks.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iD8DBQFDsa4iaI0dwg4A47wRAo14AKCbaraQkijBHpzSJdFzoTG1L/MXjgCg8VDe
130LL3/dMhRjVw4Wp8IN0a8=
=skKB
-----END PGP SIGNATURE-----
[-- Attachment #2: stack_avail.c --]
[-- Type: text/x-csrc, Size: 3915 bytes --]
/*
* stack_avail - A linux kernel module to display available stack
* If the kernel stack-poison patch has been applied, this
* module also displays available stack at maximum usage
* Copyright Frank Sorenson <frank@tuxrocks.com> 2005
*
* Permission is hereby granted to copy, modify and redistribute this code
* in terms of the GNU Library General Public License, Version 2 or later,
* at your option.
*
*/
#include <linux/module.h>
#include <linux/kallsyms.h>
static int verbose = 0;
static unsigned long sinittext;
static unsigned long einittext;
static unsigned long stext;
static unsigned long etext;
// task_struct - /UML/Source/Host/linux-2.6.15-rc5-mm3+fs3/include/linux/sched.h
// thread_struct - /UML/Source/Host/linux-2.6.15-rc5-mm3+fs3/include/asm-i386/processor.h
// thread_info - /UML/Source/Host/linux-2.6.15-rc5-mm3+fs3/include/asm-i386/thread_info.h
static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
{
return p > (void *)tinfo &&
p < (void *)tinfo + THREAD_SIZE - 3;
}
static int core_kernel_text(unsigned long addr)
{
if (addr >= (unsigned long)stext &&
addr <= (unsigned long)etext)
return 1;
if (addr >= (unsigned long)sinittext &&
addr <= (unsigned long)einittext)
return 1;
return 0;
}
int my_kernel_text_address(unsigned long addr)
{
if (core_kernel_text(addr))
return 1;
return 0;
// return __module_text_address(addr) != NULL;
}
static inline unsigned long print_context_stack(struct thread_info *tinfo,
unsigned long *stack, unsigned long ebp)
{
unsigned long addr;
#ifdef CONFIG_FRAME_POINTER
while (valid_stack_ptr(tinfo, (void *)ebp)) {
addr = *(unsigned long *)(ebp + 4);
printk(" [<%08lx>] ", addr);
print_symbol("%s", addr);
printk("\n");
ebp = *(unsigned long *)ebp;
}
#else
while (valid_stack_ptr(tinfo, stack)) {
addr = *stack++;
if (my_kernel_text_address(addr)) {
printk(" [<%08lx>]", addr);
print_symbol(" %s", addr);
printk("\n");
}
}
#endif
return ebp;
}
void show_trace(struct task_struct *task, unsigned long * stack)
{
unsigned long ebp;
ebp = *(unsigned long *) task->thread.esp;
while (1) {
struct thread_info *context;
context = (struct thread_info *)
((unsigned long)stack & (~(THREAD_SIZE - 1)));
ebp = print_context_stack(context, stack, ebp);
stack = (unsigned long*)context->previous_esp;
if (!stack)
break;
printk(" =======================\n");
}
}
static int stack_avail_load(void)
{
struct task_struct *task;
unsigned char *base_addr;
unsigned char *max_addr;
unsigned char *ptr;
unsigned long current_avail;
unsigned long poisoned_avail;
sinittext = kallsyms_lookup_name("_sinittext");
einittext = kallsyms_lookup_name("_einittext");
stext = kallsyms_lookup_name("_stext");
etext = kallsyms_lookup_name("_etext");
printk("Displaying stack space available:\n");
for_each_process(task) {
printk("%d: %s", task->pid, task->comm);
base_addr = (unsigned char *)(task->thread.esp & 0xFFFFF000);
max_addr = base_addr + THREAD_SIZE - 1;
ptr = base_addr + sizeof(struct thread_info);
while (*ptr == 'Q') {
ptr ++;
}
current_avail = (unsigned long)(task->thread.esp) -
(unsigned long)(base_addr) - sizeof(struct thread_info);
poisoned_avail = THREAD_SIZE - ((unsigned long)(max_addr - ptr)) -
sizeof(struct thread_info) - 1;
printk(" - free stack now: %lu", current_avail);
if (poisoned_avail != 0)
printk(", at max usage: %lu", poisoned_avail);
if (verbose) {
printk("\nCurrent call Trace:\n");
show_trace(task, (unsigned long *)(task->thread.esp));
}
printk("\n");
}
return 0;
}
static void stack_avail_unload(void)
{
printk("stack_avail module unloading\n");
}
module_init(stack_avail_load);
module_exit(stack_avail_unload);
module_param(verbose, int, 0);
MODULE_AUTHOR ("Frank Sorenson, frank@tuxrocks.com");
MODULE_DESCRIPTION ("Displays available stack space");
MODULE_LICENSE("GPL");
[-- Attachment #3: Makefile --]
[-- Type: text/plain, Size: 350 bytes --]
KVER := $(shell uname -r)
KSRC := /lib/modules/$(KVER)/build
PWD = $(shell pwd)
obj-m += stack_avail.o
all: modules
modules:
$(MAKE) -C $(KSRC) SUBDIRS=$(PWD) BUILD_DIR=$(PWD) modules
ioctl: ioctl.c
$(CC) $< -o $@
clean:
@find . \
\( -name '*.ko' -o -name '.*.cmd' \
-o -name '*.o' -o -name '*.mod.c' \) \
-type f -print | xargs rm -f
next prev parent reply other threads:[~2005-12-27 21:17 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-12-22 21:53 4k stacks linux-os (Dick Johnson)
2005-12-23 1:11 ` Grant Coady
2005-12-23 17:45 ` Alistair John Strachan
2005-12-23 12:56 ` Krzysztof Halasa
2005-12-24 12:03 ` Denis Vlasenko
2005-12-25 2:43 ` Andrew James Wade
2005-12-26 7:42 ` Andrew James Wade
2005-12-26 8:40 ` Andrew James Wade
2005-12-27 21:12 ` Frank Sorenson [this message]
2005-12-28 18:05 ` Grant Coady
2005-12-26 14:38 ` Diego Calleja
2005-12-28 13:14 ` linux-os (Dick Johnson)
2005-12-28 15:16 ` Denis Vlasenko
2005-12-30 14:45 ` linux-os (Dick Johnson)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43B1AE23.4020105@tuxrocks.com \
--to=frank@tuxrocks.com \
--cc=ajwade@cpe001346162bf9-cm0011ae8cd564.cpe.net.cable.rogers.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-os@analogic.com \
--cc=vda@ilport.com.ua \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.