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 The following code locks pages with mlock() system call: 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 mmap(2) , sbrk(2) , or malloc(3) , 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: Unlock all mapped pages by using munlockall() system call: Additional resources capabilities(7) and move_pages(2) man pages on your system mlock(2) and mlock(3) man pages on your system posix_memalign(3) and posix_memalign(3p) man pages on your system 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: 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) and mlockall(2) man pages on your system 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 Parameter Description 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.

Commands:
#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); }
#include <sys/mman.h> int mlockall (int flags)
#include <sys/mman.h> int munlockall (void)
#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); }