aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2006-01-18 20:42:58 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-18 22:20:21 -0500
commitb63162939cd797c8269964ce856ed1f2fec5f70e (patch)
tree666dd2919bd156aa183a87576224d0fad3c4cf72 /arch
parentb6a2b13778873bd9edd0b4a7d24a7bd730369021 (diff)
[PATCH] uml: avoid malloc to sleep in atomic sections
Ugly trick to help make malloc not sleeping - we can't do anything else. But this is not yet optimal, since spinlock don't trigger in_atomic() when preemption is disabled. Also, even if ugly, this was already used in one place, and was even more bogus. Fix it. Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/um/include/kern_util.h4
-rw-r--r--arch/um/include/user.h1
-rw-r--r--arch/um/kernel/process_kern.c21
-rw-r--r--arch/um/os-Linux/helper.c4
4 files changed, 19 insertions, 11 deletions
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 8f4e46d677ab..c649108a9e9f 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -120,8 +120,10 @@ extern void machine_halt(void);
120extern int is_syscall(unsigned long addr); 120extern int is_syscall(unsigned long addr);
121extern void arch_switch(void); 121extern void arch_switch(void);
122extern void free_irq(unsigned int, void *); 122extern void free_irq(unsigned int, void *);
123extern int um_in_interrupt(void);
124extern int cpu(void); 123extern int cpu(void);
124
125/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
126extern int __cant_sleep(void);
125extern void segv_handler(int sig, union uml_pt_regs *regs); 127extern void segv_handler(int sig, union uml_pt_regs *regs);
126extern void sigio_handler(int sig, union uml_pt_regs *regs); 128extern void sigio_handler(int sig, union uml_pt_regs *regs);
127 129
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 0f865ef46918..91b0ac4ad88c 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -18,6 +18,7 @@ extern int open_gdb_chan(void);
18extern unsigned long strlcpy(char *, const char *, unsigned long); 18extern unsigned long strlcpy(char *, const char *, unsigned long);
19extern unsigned long strlcat(char *, const char *, unsigned long); 19extern unsigned long strlcat(char *, const char *, unsigned long);
20extern void *um_vmalloc(int size); 20extern void *um_vmalloc(int size);
21extern void *um_vmalloc_atomic(int size);
21extern void vfree(void *ptr); 22extern void vfree(void *ptr);
22 23
23#endif 24#endif
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index e167cf0a71f4..3113cab8675e 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -287,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
287 287
288void *um_kmalloc(int size) 288void *um_kmalloc(int size)
289{ 289{
290 return(kmalloc(size, GFP_KERNEL)); 290 return kmalloc(size, GFP_KERNEL);
291} 291}
292 292
293void *um_kmalloc_atomic(int size) 293void *um_kmalloc_atomic(int size)
294{ 294{
295 return(kmalloc(size, GFP_ATOMIC)); 295 return kmalloc(size, GFP_ATOMIC);
296} 296}
297 297
298void *um_vmalloc(int size) 298void *um_vmalloc(int size)
299{ 299{
300 return(vmalloc(size)); 300 return vmalloc(size);
301}
302
303void *um_vmalloc_atomic(int size)
304{
305 return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
306}
307
308int __cant_sleep(void) {
309 return in_atomic() || irqs_disabled() || in_interrupt();
310 /* Is in_interrupt() really needed? */
301} 311}
302 312
303unsigned long get_fault_addr(void) 313unsigned long get_fault_addr(void)
@@ -369,11 +379,6 @@ int smp_sigio_handler(void)
369 return(0); 379 return(0);
370} 380}
371 381
372int um_in_interrupt(void)
373{
374 return(in_interrupt());
375}
376
377int cpu(void) 382int cpu(void)
378{ 383{
379 return(current_thread->cpu); 384 return(current_thread->cpu);
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 36cc8475bcda..6490a4ff40ac 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
60 60
61 if((stack_out != NULL) && (*stack_out != 0)) 61 if((stack_out != NULL) && (*stack_out != 0))
62 stack = *stack_out; 62 stack = *stack_out;
63 else stack = alloc_stack(0, um_in_interrupt()); 63 else stack = alloc_stack(0, __cant_sleep());
64 if(stack == 0) 64 if(stack == 0)
65 return(-ENOMEM); 65 return(-ENOMEM);
66 66
@@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
124 unsigned long stack, sp; 124 unsigned long stack, sp;
125 int pid, status, err; 125 int pid, status, err;
126 126
127 stack = alloc_stack(stack_order, um_in_interrupt()); 127 stack = alloc_stack(stack_order, __cant_sleep());
128 if(stack == 0) return(-ENOMEM); 128 if(stack == 0) return(-ENOMEM);
129 129
130 sp = stack + (page_size() << stack_order) - sizeof(void *); 130 sp = stack + (page_size() << stack_order) - sizeof(void *);