summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Gortmaker <paul.gortmaker@gmail.com>2006-11-02 16:41:18 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-11-30 15:27:03 +0000
commit122214428a7bfab2c09b417f3acdb06222e81748 (patch)
treef453fa01829db292b1108e87a416c1acdfedcd70
parent9b531ce242159bd26e09b55d8fb4be3f4bf75e24 (diff)
downloadlinux-stable-122214428a7bfab2c09b417f3acdb06222e81748.tar.gz
linux-stable-122214428a7bfab2c09b417f3acdb06222e81748.tar.bz2
linux-stable-122214428a7bfab2c09b417f3acdb06222e81748.zip
[ARM] 3911/2: Simplify alloc_thread_info on ARM
Remove ARM local cache of 4 struct thread_info. Can cause oops under certain circumstances. Russell indicated the original optimization was required on older kernels to avoid thread starvation on memory fragmentation, but may no longer be required. I've updated the patch to 19rc4 and ensured no <config.h> dain-bramage slipped in this time (sorry about that). Original description follows: I was given some test results which pointed to an Oops in alloc_thread_info (happened 2x), and after looking at the code, I see that ARM has its own local cache of 4 struct thread_info. There wasn't any clear (to me) synchronization between the alloc_thread_info and the free_thread_info. I looked over the other arch, and they all simply allocate them on an as needed basis, so I simplified the ARM to do the same, based on the other arch (e.g. PPC) and the folks doing the testing have indicated that this fixed the oops. Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/kernel/process.c61
-rw-r--r--include/asm-arm/thread_info.h14
2 files changed, 12 insertions, 63 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index bf35c178a877..a9e8f7e55fd6 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -281,67 +281,6 @@ void show_fpregs(struct user_fp *regs)
}
/*
- * Task structure and kernel stack allocation.
- */
-struct thread_info_list {
- unsigned long *head;
- unsigned int nr;
-};
-
-static DEFINE_PER_CPU(struct thread_info_list, thread_info_list) = { NULL, 0 };
-
-#define EXTRA_TASK_STRUCT 4
-
-struct thread_info *alloc_thread_info(struct task_struct *task)
-{
- struct thread_info *thread = NULL;
-
- if (EXTRA_TASK_STRUCT) {
- struct thread_info_list *th = &get_cpu_var(thread_info_list);
- unsigned long *p = th->head;
-
- if (p) {
- th->head = (unsigned long *)p[0];
- th->nr -= 1;
- }
- put_cpu_var(thread_info_list);
-
- thread = (struct thread_info *)p;
- }
-
- if (!thread)
- thread = (struct thread_info *)
- __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
- /*
- * The stack must be cleared if you want SYSRQ-T to
- * give sensible stack usage information
- */
- if (thread)
- memzero(thread, THREAD_SIZE);
-#endif
- return thread;
-}
-
-void free_thread_info(struct thread_info *thread)
-{
- if (EXTRA_TASK_STRUCT) {
- struct thread_info_list *th = &get_cpu_var(thread_info_list);
- if (th->nr < EXTRA_TASK_STRUCT) {
- unsigned long *p = (unsigned long *)thread;
- p[0] = (unsigned long)th->head;
- th->head = p;
- th->nr += 1;
- put_cpu_var(thread_info_list);
- return;
- }
- put_cpu_var(thread_info_list);
- }
- free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
-}
-
-/*
* Free current thread data structures etc..
*/
void exit_thread(void)
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index f28b236139ed..d9b8bddc8732 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -94,8 +94,18 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}
-extern struct thread_info *alloc_thread_info(struct task_struct *task);
-extern void free_thread_info(struct thread_info *);
+/* thread information allocation */
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk) \
+ ((struct thread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, \
+ THREAD_SIZE_ORDER))
+#else
+#define alloc_thread_info(tsk) \
+ ((struct thread_info *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
+#endif
+
+#define free_thread_info(info) \
+ free_pages((unsigned long)info, THREAD_SIZE_ORDER);
#define thread_saved_pc(tsk) \
((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc)))