Search code examples
clinux-kernel

How to acquire the "mm semaphore" in C?


If you want to use the remap_pfn_range function within a custom kernel driver implementing mmap, you know that you have to acquire the 'mm semaphore'. But it's not clear how to do so from the examples that I can find publicly available. I think it would benefit the community to edit the examples that are available, and I'm willing to do so, but I don't know where to start.

As per the documentation: this is only safe if the mm semaphore is held when called.


Solution

  • It helps to look at the actual source [for remap_pfn_range]. That's in the mm subdirectory, specifically in mm/memory.c

    There you'll see struct mm_struct *mm = vma->vm_mm; so that's the mm you want. Note that is also [probably] current->mm

    If you look around in a few more files there [notably mm/mmap.c], you'll see down_write(&mm->mmap_sem) and up_write(&mm->mmap_sem) [which are the kernel's semaphore primitives]. Note that if you only needed to read from the area, there are down_read and up_read

    So, to put it all together:

    void
    myfnc(...)
    {
        struct vm_area_struct *vma = ...;
        struct mm_struct *mm = vma->vm_mm;
    
        ...
    
        down_write(&mm->mmap_sem);
        remap_pfn_range(vma,...);
        up_write(&mm->mmap_sem);
    
        ...
    }
    

    Documentation aside, one of the best ways to find these things is the look through the source itself. I've been writing linux kernel/driver code for 20+ years and it's what I do when I need to find something that I don't know about.