0001
0002
0003
0004 #include <linux/fs.h>
0005 #include <linux/mm.h>
0006 #include <linux/mman.h>
0007 #include <linux/shm.h>
0008 #include <linux/sched.h>
0009 #include <linux/random.h>
0010 #include <linux/io.h>
0011
0012 #define COLOUR_ALIGN(addr,pgoff) \
0013 ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \
0014 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 unsigned long
0025 arch_get_unmapped_area(struct file *filp, unsigned long addr,
0026 unsigned long len, unsigned long pgoff, unsigned long flags)
0027 {
0028 struct mm_struct *mm = current->mm;
0029 struct vm_area_struct *vma;
0030 int do_align = 0;
0031 struct vm_unmapped_area_info info;
0032
0033
0034
0035
0036
0037 do_align = filp || (flags & MAP_SHARED);
0038
0039
0040
0041
0042 if (flags & MAP_FIXED) {
0043 if (flags & MAP_SHARED &&
0044 (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
0045 return -EINVAL;
0046 return addr;
0047 }
0048
0049 if (len > TASK_SIZE)
0050 return -ENOMEM;
0051
0052 if (addr) {
0053 if (do_align)
0054 addr = COLOUR_ALIGN(addr, pgoff);
0055 else
0056 addr = PAGE_ALIGN(addr);
0057
0058 vma = find_vma(mm, addr);
0059 if (TASK_SIZE - len >= addr &&
0060 (!vma || addr + len <= vm_start_gap(vma)))
0061 return addr;
0062 }
0063
0064 info.flags = 0;
0065 info.length = len;
0066 info.low_limit = mm->mmap_base;
0067 info.high_limit = TASK_SIZE;
0068 info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
0069 info.align_offset = pgoff << PAGE_SHIFT;
0070 return vm_unmapped_area(&info);
0071 }