Chapter 10. Using mlock() system calls on RHEL for Real Time

The RHEL for Real-Time memory lock (mlock()) function enables the real-time calling processes to lock or unlock a specified range of the address space. This range prevents Linux from paging the locked memory when swapping memory space. After you allocate the physical page to the page table entry, references to that page become fast. The mlock() system calls include two functions: mlock() and mlockall(). Similarly, munlock() system call includes the munlock() and munlockall() functions.

10.1. mlock() and munlock() system calls

The mlock() and mlockall() system calls lock a specified memory range and do not page this memory. The following are the mlock() system call groups:

  • mlock() system calls: lock a specified range of address.
  • munlock() system calls: unlock a specified range of address.

The mlock() system calls, lock pages in the address range starting at addr and continuing for len bytes. When the call returns successfully, all pages that contain a part of the specified address range stay in the memory until unlocked later.

With mlockall() system calls, you can lock all mapped pages into the specified address range. Memory locks do not stack. Any page locked by several calls will unlock the specified address range or the entire region with a single munlock() system call. With munlockall() system calls, you can unlock the entire program space.

The status of the pages contained in a specific range depends on the value in the flags argument. The flags argument can be 0 or MLOCK_ONFAULT.

Memory locks are not inherited by a child process through fork and automatically removed when a process terminates.

Warning

Use mlock() system calls with caution. Excessive use can cause out-of-memory (OOM) errors. When an application is large or if it has a large data domain, the mlock() calls can cause thrashing when the system is not able to allocate memory for other tasks.

When using mlockall() calls for real-time processes, ensure that you reserve sufficient stack pages.

10.2. Using mlock() system calls to lock pages

The real-time mlock() system calls use the addr parameter to specify the start of an address range and len to define the length of the address space in bytes. The alloc_workbuf() function dynamically allocates a memory buffer and locks it. Memory allocation is done by the posix_memalig() function to align the memory area to a page. The function free_workbuf() unlocks the memory area.

Prerequisites:

  • You have root privileges or the CAP_IPC_LOCK capability to use mlockall() or mlock() on large buffers

Procedure

  • To lock pages with mlock() system call, run the following command:

    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/mman.h>
    
    void *alloc_workbuf(size_t size)
    {
      void ptr;
      int retval;
    
      // alloc memory aligned to a page, to prevent two mlock() in the same page.
      retval = posix_memalign(&ptr, (size_t) sysconf(_SC_PAGESIZE), size);
    
      // return NULL on failure
      if (retval)
        return NULL;
    
      // lock this buffer into RAM
      if (mlock(ptr, size)) {
        free(ptr);
        return NULL;
      }
        return ptr;
     }
    
    void free_workbuf(void *ptr, size_t size) {
      // unlock the address range
      munlock(ptr, size);
    
      // free the memory
      free(ptr);
    }

Verification

The real-time mlock() and munlock() calls return 0 when successful. In case of an error, they return -1 and set a errno to indicate the error.

10.3. Using mlockall() system calls to lock all mapped pages

To lock and unlock real-time memory with mlockall() and munlockall() system calls, set the flags argument to 0 or one of the constants: MCL_CURRENT or MCL_FUTURE. With MCL_FUTURE, a future system call, such as mmap2(), sbrk2(), or malloc3(), might fail, because it causes the number of locked bytes to exceed the permitted maximum.

Prerequisites

  • You have root permissions on the system.

Procedure

  • To use mlockall() and munlockall() real-time system calls :

    • Lock all mapped pages by using mlockall() system call:

      #include <sys/mman.h>
      int mlockall (int flags)
    • Unlock all mapped pages by using munlockall() system call:

      #include <sys/mman.h>
      int munlockall (void)

Additional resources

  • capabilities(7) man page
  • mlock(2) man page
  • mlock(3) man page
  • move_pages(2) man page
  • posix_memalign(3) man page
  • posix_memalign(3p) man page

10.4. Using mmap() system calls to map files or devices into memory

For large memory allocations on real-time systems, the memory allocation (malloc) method uses the mmap() system call to find memory space. You can assign and lock memory areas by setting MAP_LOCKED in the flags parameter. As mmap() assigns memory on a page basis, it avoids two locks on the same page, which prevents the double-lock or single-unlock problems.

Prerequisites

  • You have root permissions on the system.

Procedure

  • To map a specific process-address space:

    #include <sys/mman.h>
    #include <stdlib.h>
    
    void *alloc_workbuf(size_t size)
    {
     void *ptr;
    
     ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0);
    
     if (ptr == MAP_FAILED)
      return NULL;
    
     return ptr;
    }
    
    void
    free_workbuf(void *ptr, size_t size)
    {
     munmap(ptr, size);
    }

Verification

  • When the mmap() function completes successfully, it returns a pointer to the mapped area. On error, it returns the MAP_FAILED value and sets a errno to indicate the error.
  • When the munmap() function completes successfully, it returns 0. On error, it returns -1 and sets an errno to indicate the error.

Additional resources

  • mmap(2) man page
  • mlockall(2) man page

10.5. Parameters for mlock() system calls

The parameters for memory lock system call and the functions they perform are listed and described in the mlock parameters table.

Table 10.1. mlock parameters

ParameterDescription

addr

Specifies the process address space to lock or unlock. When NULL, the kernel chooses the page-aligned arrangement of data in the memory. If addr is not NULL, the kernel chooses a nearby page boundary, which is always above or equal to the value specified in /proc/sys/vm/mmap_min_addr file.

len

Specifies the length of the mapping, which must be greater than 0.

fd

Specifies the file descriptor.

prot

mmap and munmap calls define the desired memory protection with this parameter. prot takes one or a combination of PROT_EXEC, PROT_READ, PROT_WRITE or PROT_NONE values.

flags

Controls the mapping visibility to other processes that map the same file. It takes one of the values: MAP_ANONYMOUS, MAP_LOCKED, MAP_PRIVATE or MAP_SHARED values.

MCL_CURRENT

Locks all pages that are currently mapped into a process.

MCL_FUTURE

Sets the mode to lock subsequent memory allocations. These could be new pages required by a growing heap and stack, new memory-mapped files, or shared memory regions.