Finding a free interval archgetunmappedarea

The arch_get_unmapped_area( ) function searches the process address space to find an available linear address interval. The len parameter specifies the interval length, while the addr parameter may specify the address from which the search is started. If the search is successful, the function returns the initial address of the new interval; otherwise, it returns the error code -


return -ENOMEM; addr = (addr + Oxfff) & 0xfffff000; if (addr && addr + len <= TASK_SIZE) { vma = find_vma(current->mm, addr); if (!vma || addr + len <= vma->vm_start) return addr;

for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { if (addr + len > TASK_SIZE)

return -ENOMEM; if (!vma || addr + len <= vma->vm_start)

The function starts by checking to make sure the interval length is within the limit imposed on User Mode linear addresses, usually 3 GB. If addr is different from zero, the function tries to allocate the interval starting from addr. To be on the safe side, the function rounds up the value of addr to a multiple of 4 KB. If addr is 0 or the previous search failed, the search's starting point is set to one-third of the User Mode linear address space. Starting from addr, the function then repeatedly invokes find_vma( ) with increasing values of addr to find the required free interval. During this search, the following cases may occur:

• The requested interval is larger than the portion of linear address space yet to be scanned (addr + len > task_size). Since there are not enough linear addresses to satisfy the request, return -enomem.

• The hole following the last scanned region is not large enough (vma != NULL && vma->vm_start < addr + len). Consider the next region.

• If neither one of the preceding conditions holds, a large enough hole has been found. Return addr. Inserting a region in the memory descriptor list: insert_vm_struct( )

insert_vm_struct( ) inserts a vm_area_struct structure in the memory region object list and red-black tree of a memory descriptor. It uses two parameters: mm, which specifies the address of a process memory descriptor, and vma, which specifies the address of the vm_area_struct object to be inserted. The vm_start and vm_end fields of the memory region object must have already been initialized. The function invokes the find_vma_prepare( ) function to look up the position in the red-black tree mm->mm_rb where vma should go. Then insert_vm_struct( ) invokes the vma_link( ) function, which in turn:

1. Acquires the mm->page_table_lock spin lock.

2. Inserts the memory region in the linked list referenced by mm->mmap.

3. Inserts the memory region in the red-black tree mm->mm_rb.

4. Releases the mm->page_table_lock spin lock.

5. Increments by 1 the mm->map_count counter.

If the region contains a memory-mapped file, the vma_link( ) function performs additional tasks that are described in Chapter 16.

The kernel also defines the _ _insert_vm_struct( ) function, which is identical to insert_vm_struct( ) but doesn't acquire any lock before modifying the memory region data structures referenced by mm. The kernel uses it when it is sure that no concurrent accesses to the memory region data structures can happen—for instance, because it already acquired a suitable lock.

The _ _vma_unlink( ) function receives as parameter a memory descriptor address mm and two memory region object addresses vma and prev. Both memory regions should belong to mm, and prev should precede vma in the memory region ordering. The function removes vma from the linked list and the red-black tree of the memory descriptor.

Continue reading here: Allocating a Linear Address Interval

Was this article helpful?

0 0