[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>
This commit is contained in:
parent
b6a2b13778
commit
b63162939c
4 changed files with 19 additions and 11 deletions
|
@ -120,8 +120,10 @@ extern void machine_halt(void);
|
|||
extern int is_syscall(unsigned long addr);
|
||||
extern void arch_switch(void);
|
||||
extern void free_irq(unsigned int, void *);
|
||||
extern int um_in_interrupt(void);
|
||||
extern int cpu(void);
|
||||
|
||||
/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
|
||||
extern int __cant_sleep(void);
|
||||
extern void segv_handler(int sig, union uml_pt_regs *regs);
|
||||
extern void sigio_handler(int sig, union uml_pt_regs *regs);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ extern int open_gdb_chan(void);
|
|||
extern unsigned long strlcpy(char *, const char *, unsigned long);
|
||||
extern unsigned long strlcat(char *, const char *, unsigned long);
|
||||
extern void *um_vmalloc(int size);
|
||||
extern void *um_vmalloc_atomic(int size);
|
||||
extern void vfree(void *ptr);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -287,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
|
|||
|
||||
void *um_kmalloc(int size)
|
||||
{
|
||||
return(kmalloc(size, GFP_KERNEL));
|
||||
return kmalloc(size, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void *um_kmalloc_atomic(int size)
|
||||
{
|
||||
return(kmalloc(size, GFP_ATOMIC));
|
||||
return kmalloc(size, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
void *um_vmalloc(int size)
|
||||
{
|
||||
return(vmalloc(size));
|
||||
return vmalloc(size);
|
||||
}
|
||||
|
||||
void *um_vmalloc_atomic(int size)
|
||||
{
|
||||
return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
|
||||
}
|
||||
|
||||
int __cant_sleep(void) {
|
||||
return in_atomic() || irqs_disabled() || in_interrupt();
|
||||
/* Is in_interrupt() really needed? */
|
||||
}
|
||||
|
||||
unsigned long get_fault_addr(void)
|
||||
|
@ -369,11 +379,6 @@ int smp_sigio_handler(void)
|
|||
return(0);
|
||||
}
|
||||
|
||||
int um_in_interrupt(void)
|
||||
{
|
||||
return(in_interrupt());
|
||||
}
|
||||
|
||||
int cpu(void)
|
||||
{
|
||||
return(current_thread->cpu);
|
||||
|
|
|
@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
|
|||
|
||||
if((stack_out != NULL) && (*stack_out != 0))
|
||||
stack = *stack_out;
|
||||
else stack = alloc_stack(0, um_in_interrupt());
|
||||
else stack = alloc_stack(0, __cant_sleep());
|
||||
if(stack == 0)
|
||||
return(-ENOMEM);
|
||||
|
||||
|
@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
|
|||
unsigned long stack, sp;
|
||||
int pid, status, err;
|
||||
|
||||
stack = alloc_stack(stack_order, um_in_interrupt());
|
||||
stack = alloc_stack(stack_order, __cant_sleep());
|
||||
if(stack == 0) return(-ENOMEM);
|
||||
|
||||
sp = stack + (page_size() << stack_order) - sizeof(void *);
|
||||
|
|
Loading…
Reference in a new issue