diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-04-11 23:18:43 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-11 23:18:43 -0700 |
| commit | 95f238eac82907c4ccbc301cd5788e67db0715ce (patch) | |
| tree | 2f93af2a5918f304a00bae74ff5018e4932184b7 /include | |
| parent | 124187e5946cb24afbfb41eecfcf9e7ff70b84b0 (diff) | |
[PATCH] ia32: 4Kb stacks (and irqstacks) patch
From: Arjan van de Ven <arjanv@redhat.com>
Below is a patch to enable 4Kb stacks for x86. The goal of this is to
1) Reduce footprint per thread so that systems can run many more threads
(for the java people)
2) Reduce the pressure on the VM for order > 0 allocations. We see real life
workloads (granted with 2.4 but the fundamental fragmentation issue isn't
solved in 2.6 and isn't solvable in theory) where this can be a problem.
In addition order > 0 allocations can make the VM "stutter" and give more
latency due to having to do much much more work trying to defragment
The first 2 bits of the patch actually affect compiler options in a generic
way: I propose to disable the -funit-at-a-time feature from gcc. With this
enabled (and it's default with -O2), gcc will very agressively inline
functions, which is nice and all for userspace, but for the kernel this makes
us suffer a gcc deficiency more: gcc is extremely bad at sharing stackslots,
for example a situation like this:
if (some_condition)
function_A();
else
function_B();
with -funit-at-a-time, both function_A() and _B() might get inlined, however
the stack usage of both functions of the parent function grows the stack
usage of both functions COMBINED instead of the maximum of the two. Even
with the normal 8Kb stacks this is a danger since we see some functions grow
3Kb to 4Kb of stack use this way. With 4Kb stacks, 4Kb of stack usage growth
obviously is deadly ;-( but even with 8Kb stacks it's pure lottery.
Disabling -funit-at-a-time also exposes another thing in the -mm tree; the
attribute always_inline is considered harmful by gcc folks in that when gcc
makes a decision to NOT inline a function marked this way, it throws an
error. Disabling -funit-at-a-time disables some of the agressive inlining
(eg of large functions that come later in the .c file) so this would make
your tree not compile.
The 4k stackness of the kernel is included in modversions, so people don't
load 4k-stack modules into 8k-stack kernels.
At present 4k stacks are selectable in config. When the feature has settled
in we should remove the 8k option. This will break the nvidia modules. But
Fedora uses 4k stacks so a new nvidia driver is expected soon.
Diffstat (limited to 'include')
| -rw-r--r-- | include/asm-alpha/irq.h | 3 | ||||
| -rw-r--r-- | include/asm-arm/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-arm26/irq.h | 2 | ||||
| -rw-r--r-- | include/asm-cris/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-h8300/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-i386/irq.h | 25 | ||||
| -rw-r--r-- | include/asm-i386/module.h | 8 | ||||
| -rw-r--r-- | include/asm-i386/thread_info.h | 24 | ||||
| -rw-r--r-- | include/asm-ia64/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-m68k/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-m68knommu/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-mips/irq.h | 3 | ||||
| -rw-r--r-- | include/asm-parisc/irq.h | 3 | ||||
| -rw-r--r-- | include/asm-ppc/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-ppc64/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-s390/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-sh/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-sparc/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-sparc64/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-um/irq.h | 5 | ||||
| -rw-r--r-- | include/asm-v850/irq.h | 4 | ||||
| -rw-r--r-- | include/asm-x86_64/irq.h | 4 | ||||
| -rw-r--r-- | include/linux/compiler-gcc3.h | 2 | ||||
| -rw-r--r-- | include/linux/irq.h | 1 |
24 files changed, 126 insertions, 6 deletions
diff --git a/include/asm-alpha/irq.h b/include/asm-alpha/irq.h index 551c7308c642..566db720000a 100644 --- a/include/asm-alpha/irq.h +++ b/include/asm-alpha/irq.h @@ -93,5 +93,8 @@ extern void enable_irq(unsigned int); struct pt_regs; extern void (*perf_irq)(unsigned long, struct pt_regs *); +struct irqaction; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ALPHA_IRQ_H */ diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h index a89f7345ed39..286be7cf7c63 100644 --- a/include/asm-arm/irq.h +++ b/include/asm-arm/irq.h @@ -44,5 +44,9 @@ void disable_irq_wake(unsigned int irq); void enable_irq_wake(unsigned int irq); int setup_irq(unsigned int, struct irqaction *); +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff --git a/include/asm-arm26/irq.h b/include/asm-arm26/irq.h index 68712e576c6f..06bd5a543d13 100644 --- a/include/asm-arm26/irq.h +++ b/include/asm-arm26/irq.h @@ -45,6 +45,8 @@ extern void enable_irq(unsigned int); int set_irq_type(unsigned int irq, unsigned int type); int setup_irq(unsigned int, struct irqaction *); +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); #endif diff --git a/include/asm-cris/irq.h b/include/asm-cris/irq.h index caa45facb1b2..87f342517bb1 100644 --- a/include/asm-cris/irq.h +++ b/include/asm-cris/irq.h @@ -14,6 +14,10 @@ extern void enable_irq(unsigned int); #define disable_irq_nosync disable_irq #define enable_irq_nosync enable_irq +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ diff --git a/include/asm-h8300/irq.h b/include/asm-h8300/irq.h index fabde1dd34a1..5027181ed067 100644 --- a/include/asm-h8300/irq.h +++ b/include/asm-h8300/irq.h @@ -68,4 +68,8 @@ extern void disable_irq(unsigned int); #define enable_irq_nosync(x) enable_irq(x) #define disable_irq_nosync(x) disable_irq(x) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _H8300_IRQ_H_ */ diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h index 69cb661b012a..5649b4a79bb2 100644 --- a/include/asm-i386/irq.h +++ b/include/asm-i386/irq.h @@ -14,6 +14,7 @@ #include <linux/sched.h> /* include comes from machine specific directory */ #include "irq_vectors.h" +#include <asm/thread_info.h> static __inline__ int irq_canonicalize(int irq) { @@ -30,4 +31,28 @@ extern int can_request_irq(unsigned int, unsigned long flags); #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif +#ifdef CONFIG_4KSTACKS +/* + * per-CPU IRQ handling contexts (thread information and stack) + */ +union irq_ctx { + struct thread_info tinfo; + u32 stack[THREAD_SIZE/sizeof(u32)]; +}; + +extern union irq_ctx *hardirq_ctx[NR_CPUS]; +extern union irq_ctx *softirq_ctx[NR_CPUS]; + +extern void irq_ctx_init(int cpu); + +#define __ARCH_HAS_DO_SOFTIRQ +#else +#define irq_ctx_init(cpu) do { ; } while (0) +#endif + +struct irqaction; +struct pt_regs; +asmlinkage int handle_IRQ_event(unsigned int, struct pt_regs *, + struct irqaction *); + #endif /* _ASM_IRQ_H */ diff --git a/include/asm-i386/module.h b/include/asm-i386/module.h index 76fc36f60ebe..8ec1dae638cb 100644 --- a/include/asm-i386/module.h +++ b/include/asm-i386/module.h @@ -60,6 +60,12 @@ struct mod_arch_specific #define MODULE_REGPARM "" #endif -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM +#ifdef CONFIG_4KSTACKS +#define MODULE_STACKSIZE "4KSTACKS " +#else +#define MODULE_STACKSIZE "" +#endif + +#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE #endif /* _ASM_I386_MODULE_H */ diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h index 75f940011daa..da5c780f2c5c 100644 --- a/include/asm-i386/thread_info.h +++ b/include/asm-i386/thread_info.h @@ -9,6 +9,9 @@ #ifdef __KERNEL__ +#include <linux/config.h> +#include <asm/page.h> + #ifndef __ASSEMBLY__ #include <asm/processor.h> #endif @@ -29,12 +32,16 @@ struct thread_info { __u32 cpu; /* current CPU */ __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ + mm_segment_t addr_limit; /* thread address space: 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernel-thread */ struct restart_block restart_block; + unsigned long previous_esp; /* ESP of the previous stack in case + of nested (IRQ) stacks + */ __u8 supervisor_stack[0]; }; @@ -53,7 +60,13 @@ struct thread_info { #endif #define PREEMPT_ACTIVE 0x4000000 +#ifdef CONFIG_4KSTACKS +#define THREAD_SIZE (4096) +#else +#define THREAD_SIZE (8192) +#endif +#define STACK_WARN (THREAD_SIZE/8) /* * macros/functions for gaining access to the thread information structure * @@ -77,7 +90,6 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) -#define THREAD_SIZE (2*PAGE_SIZE) /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) @@ -87,6 +99,14 @@ static inline struct thread_info *current_thread_info(void) return ti; } +/* how to get the current stack pointer from C */ +static inline unsigned long current_stack_pointer(void) +{ + unsigned long ti; + __asm__("movl %%esp,%0; ":"=r" (ti) : ); + return ti; +} + /* thread information allocation */ #ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ @@ -108,8 +128,6 @@ static inline struct thread_info *current_thread_info(void) #else /* !__ASSEMBLY__ */ -#define THREAD_SIZE 8192 - /* how to get the thread information struct from ASM */ #define GET_THREAD_INFO(reg) \ movl $-THREAD_SIZE, reg; \ diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h index 79479e2c6966..5d930fdc0bea 100644 --- a/include/asm-ia64/irq.h +++ b/include/asm-ia64/irq.h @@ -30,4 +30,8 @@ extern void disable_irq_nosync (unsigned int); extern void enable_irq (unsigned int); extern void set_irq_affinity_info (unsigned int irq, int dest, int redir); +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IA64_IRQ_H */ diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h index 02855ca536b0..5889bc919e80 100644 --- a/include/asm-m68k/irq.h +++ b/include/asm-m68k/irq.h @@ -124,4 +124,8 @@ extern volatile unsigned int num_spurious; */ extern irq_node_t *new_irq_node(void); +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _M68K_IRQ_H_ */ diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h index 4c66ba93201a..208ccd969e4b 100644 --- a/include/asm-m68knommu/irq.h +++ b/include/asm-m68knommu/irq.h @@ -121,4 +121,8 @@ extern irq_node_t *new_irq_node(void); #define enable_irq_nosync(x) enable_irq(x) #define disable_irq_nosync(x) disable_irq(x) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _M68K_IRQ_H_ */ diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h index 90b4ae1258a8..d9667a8fbbfb 100644 --- a/include/asm-mips/irq.h +++ b/include/asm-mips/irq.h @@ -31,4 +31,7 @@ extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); extern void init_generic_irq(void); +struct irqaction; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h index 39db70230740..b7acca7de670 100644 --- a/include/asm-parisc/irq.h +++ b/include/asm-parisc/irq.h @@ -96,4 +96,7 @@ extern unsigned long txn_alloc_addr(int); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; +struct irqaction; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_PARISC_IRQ_H */ diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h index bfa3de404d27..df5b76306f7a 100644 --- a/include/asm-ppc/irq.h +++ b/include/asm-ppc/irq.h @@ -211,5 +211,9 @@ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; extern atomic_t ppc_n_lost_interrupts; +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ #endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h index 949e19f96be1..2cd77b4935fb 100644 --- a/include/asm-ppc64/irq.h +++ b/include/asm-ppc64/irq.h @@ -75,5 +75,9 @@ static __inline__ int irq_canonicalize(int irq) return irq; } +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ #endif /* __KERNEL__ */ diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h index 25f1808531cc..cac6b3080725 100644 --- a/include/asm-s390/irq.h +++ b/include/asm-s390/irq.h @@ -21,6 +21,10 @@ enum interruption_class { #define touch_nmi_watchdog() do { } while(0) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* __KERNEL__ */ #endif diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index f470f758057a..7dd2a5ae10b5 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -329,4 +329,8 @@ static inline int generic_irq_demux(int irq) #define irq_canonicalize(irq) (irq) #define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq)) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* __ASM_SH_IRQ_H */ diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h index 5423905ffb40..cee356b0dae3 100644 --- a/include/asm-sparc/irq.h +++ b/include/asm-sparc/irq.h @@ -184,4 +184,8 @@ extern struct sun4m_intregs *sun4m_interrupts; #define SUN4M_INT_SBUS(x) (1 << (x+7)) #define SUN4M_INT_VME(x) (1 << (x)) +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index e3ba6bc2cc3e..3aef0ca67750 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -150,4 +150,8 @@ static __inline__ unsigned long get_softint(void) return retval; } +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff --git a/include/asm-um/irq.h b/include/asm-um/irq.h index cd580acadc71..8300c209a1bc 100644 --- a/include/asm-um/irq.h +++ b/include/asm-um/irq.h @@ -32,4 +32,9 @@ extern int um_request_irq(unsigned int irq, int fd, int type, void (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id); + +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif diff --git a/include/asm-v850/irq.h b/include/asm-v850/irq.h index 63e682d70de1..90c83aa053c8 100644 --- a/include/asm-v850/irq.h +++ b/include/asm-v850/irq.h @@ -65,4 +65,8 @@ extern void disable_irq_nosync (unsigned int irq); #endif /* !__ASSEMBLY__ */ +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* __V850_IRQ_H__ */ diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h index ad5445ee7460..37c9fd65c97f 100644 --- a/include/asm-x86_64/irq.h +++ b/include/asm-x86_64/irq.h @@ -53,4 +53,8 @@ extern int can_request_irq(unsigned int, unsigned long flags); #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #endif +struct irqaction; +struct pt_regs; +int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); + #endif /* _ASM_IRQ_H */ diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h index c472cac3029d..265dad4c3cb4 100644 --- a/include/linux/compiler-gcc3.h +++ b/include/linux/compiler-gcc3.h @@ -3,7 +3,7 @@ /* These definitions are for GCC v3.x. */ #include <linux/compiler-gcc.h> -#if __GNUC_MINOR__ >= 1 +#if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4 # define inline __inline__ __attribute__((always_inline)) # define __inline__ __inline__ __attribute__((always_inline)) # define __inline __inline__ __attribute__((always_inline)) diff --git a/include/linux/irq.h b/include/linux/irq.h index fa03b836c29a..5bc740d9bc47 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -71,7 +71,6 @@ extern irq_desc_t irq_desc [NR_IRQS]; #include <asm/hw_irq.h> /* the arch dependent stuff */ -extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern int setup_irq(unsigned int , struct irqaction * ); extern hw_irq_controller no_irq_type; /* needed in every arch ? */ |
