Memory Management Approach for Swapless Embedded Systems

This article presents a strategy for managing memory allocation in swapless, embedded systems to help you avoid system slowness and the dreaded Out-of-Memory killer exception.
Low Memory Watermark (LMW) Module

LMW is a kernel module based on the Linux Security Module (LSM) framework. It implements a heuristic to check the physical memory consumption threshold for denying memory allocation and notifying user space to free up memory. A user-space process terminator can be employed to free up memory. Formulas for low memory watermark thresholds are as follows:

  • deny_threshold = physical_memory * deny_percentage

  • notify_threshold = physical_memory * notify_percentage

physical_memory is the system's main memory and is represented by the kernel global variable totalram_pages. deny_percentage and notify_percentage are tunable kernel parameters, and the value of these can be altered through the sysctl interface. These parameters are bound to the /proc filesystem and can be written to and read from, using standard commands such as echo and cat. These parameters may be handled as follows:

$ echo 110 > /proc/sys/vm/lowmem_deny_watermark

$ echo 90 > /proc/sys/vm/lowmem_notify_watermark

$ cat /proc/sys/vm/lowmem_deny_watermark

$ cat /proc/sys/vm/lowmem_notify_watermark

The LWM architecture is illustrated in Figure 2. Basically, LWM overrides the kernel default overcommit behaviour by setting the vm_enough_memory function pointer field in the security_operations structure to point to the function low_vm_enough_memory(). low_vm_enough_memory() implements a heuristic based on the formula described earlier. Binding vm_enough_memory to low_vm_enough_memory() permits interception of all requests for allocation of memory pages in order to verify whether the committed virtual memory has reached the MAT or ST watermarks. Listing 1 presents how the MAT and ST watermarks are implemented in the low_vm_enough_memory() function.

Figure 2. Low Memory Watermark Architecture

The code in Listing 1 is explained below:

  • Lines 7, 8: verify whether the current process has root privileges.

  • Lines 10, 11: if MAT or ST watermarks are zero, perform the default overcommit behaviour.

  • Lines 13–16: calculate the low memory watermark thresholds.

  • Line 18: the pages are committed to update the amount of vm_committed_space.

  • Line 19: the amount of committed memory is acquired.

  • Line 20: verify whether committed memory has reached the MAT watermark.

  • Line 21: set a flag state to 1 if MAT has been reached—state=1 means any (or both) of the two thresholds was reached.

  • Lines 22, 23: do not deny memory allocation for root programs—allocation is successful for these.

  • Line 24: uncommit the current committed pages since MAT was reached.

  • Line 25: return no memory available message.

  • Line 26: verify whether committed memory has reached the ST watermark.

  • Lines 27, 28: set the state to 1, and allocation has succeeded.

  • Line 30: set the state to 0 (if no threshold was reached).

  • Line 31: memory allocation has succeeded.

The enter_watermark_state() function determines whether the low memory watermark condition has been reached and eventually sends the LMS to user space. A global boolean variable, lowmem_watermark_reached, marks the state of entering or exiting from low memory watermark conditions, being assigned to a value of 1 or 0, respectively. LMS is dispatched whenever a change in the value of this variable occurs.