Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 338763
b: refs/heads/master
c: b666186
h: refs/heads/master
i:
  338761: daa1fe2
  338759: 055ba41
v: v3
  • Loading branch information
Michel Lespinasse authored and Linus Torvalds committed Dec 12, 2012
1 parent f0296a7 commit d80c56b
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 95 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cdc17344959e30ba8d0b98448832514024282e14
refs/heads/master: b6661861777940b05934169d8a3f9207cd718996
111 changes: 17 additions & 94 deletions trunk/arch/mips/mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,6 @@ static unsigned long mmap_base(unsigned long rnd)
return PAGE_ALIGN(TASK_SIZE - gap - rnd);
}

static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr,
unsigned long pgoff)
{
unsigned long base = addr & ~shm_align_mask;
unsigned long off = (pgoff << PAGE_SHIFT) & shm_align_mask;

if (base + off <= addr)
return base + off;

return base - off;
}

#define COLOUR_ALIGN(addr, pgoff) \
((((addr) + shm_align_mask) & ~shm_align_mask) + \
(((pgoff) << PAGE_SHIFT) & shm_align_mask))
Expand All @@ -71,6 +59,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
struct vm_area_struct *vma;
unsigned long addr = addr0;
int do_color_align;
struct vm_unmapped_area_info info;

if (unlikely(len > TASK_SIZE))
return -ENOMEM;
Expand Down Expand Up @@ -107,97 +96,31 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
return addr;
}

if (dir == UP) {
addr = mm->mmap_base;
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
else
addr = PAGE_ALIGN(addr);
info.length = len;
info.align_mask = do_color_align ? (PAGE_MASK & shm_align_mask) : 0;
info.align_offset = pgoff << PAGE_SHIFT;

for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
if (TASK_SIZE - len < addr)
return -ENOMEM;
if (!vma || addr + len <= vma->vm_start)
return addr;
addr = vma->vm_end;
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
}
} else {
/* check if free_area_cache is useful for us */
if (len <= mm->cached_hole_size) {
mm->cached_hole_size = 0;
mm->free_area_cache = mm->mmap_base;
}
if (dir == DOWN) {
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
info.low_limit = PAGE_SIZE;
info.high_limit = mm->mmap_base;
addr = vm_unmapped_area(&info);

if (!(addr & ~PAGE_MASK))
return addr;

/*
* either no address requested, or the mapping can't fit into
* the requested address hole
*/
addr = mm->free_area_cache;
if (do_color_align) {
unsigned long base =
COLOUR_ALIGN_DOWN(addr - len, pgoff);
addr = base + len;
}

/* make sure it can fit in the remaining address space */
if (likely(addr > len)) {
vma = find_vma(mm, addr - len);
if (!vma || addr <= vma->vm_start) {
/* cache the address as a hint for next time */
return mm->free_area_cache = addr - len;
}
}

if (unlikely(mm->mmap_base < len))
goto bottomup;

addr = mm->mmap_base - len;
if (do_color_align)
addr = COLOUR_ALIGN_DOWN(addr, pgoff);

do {
/*
* Lookup failure means no vma is above this address,
* else if new region fits below vma->vm_start,
* return with success:
*/
vma = find_vma(mm, addr);
if (likely(!vma || addr + len <= vma->vm_start)) {
/* cache the address as a hint for next time */
return mm->free_area_cache = addr;
}

/* remember the largest hole we saw so far */
if (addr + mm->cached_hole_size < vma->vm_start)
mm->cached_hole_size = vma->vm_start - addr;

/* try just below the current vma->vm_start */
addr = vma->vm_start - len;
if (do_color_align)
addr = COLOUR_ALIGN_DOWN(addr, pgoff);
} while (likely(len < vma->vm_start));

bottomup:
/*
* A failed mmap() very likely causes application failure,
* so fall back to the bottom-up function here. This scenario
* can happen with large stack limits and large mmap()
* allocations.
*/
mm->cached_hole_size = ~0UL;
mm->free_area_cache = TASK_UNMAPPED_BASE;
addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
/*
* Restore the topdown base:
*/
mm->free_area_cache = mm->mmap_base;
mm->cached_hole_size = ~0UL;

return addr;
}

info.flags = 0;
info.low_limit = mm->mmap_base;
info.high_limit = TASK_SIZE;
return vm_unmapped_area(&info);
}

unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
Expand Down

0 comments on commit d80c56b

Please sign in to comment.