A memory management method based on hierarchical VMA
By employing a hierarchical VMA management approach, using range locks and adaptive caching, the problems of lock contention and cache contention in the Linux kernel are solved, thereby improving the multi-core performance and lookup efficiency of memory management.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- BEIJING LINX SOFTWARE CORP
- Filing Date
- 2026-06-22
- Publication Date
- 2026-07-21
AI Technical Summary
The existing Linux kernel has issues with lock contention, cache line contention, and low VMA lookup efficiency caused by global mmap_lock, which seriously affects memory management performance, especially in multi-core scenarios.
A hierarchical VMA management approach is adopted, replacing the global mmap_lock with a range lock, and using fine-grained spin locks and adaptive caching algorithms to construct a hierarchical VMA tree, thereby improving lookup efficiency and cache hit rate.
It significantly improves memory usage performance in multi-core scenarios, reduces cache consistency traffic and lock access latency, and enhances VMA lookup speed and page fault handling efficiency.
Smart Images

Figure CN122431905A_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of memory management technology, and in particular to a memory management method based on hierarchical VMA. Background Technology
[0002] With the widespread adoption of multi-core processors, the number of cores in modern computer systems has expanded from tens to hundreds, posing a significant challenge to the concurrent performance of operating system kernel memory management. As a mainstream server operating system, the Linux kernel's memory management subsystem is responsible for managing the virtual address space of processes. Its core data structures include Virtual Memory Areas (VMAs) and multi-level page tables. The VMA describes the permissions, attributes, and mapping relationships of a contiguous segment of virtual addresses in a process's address space, while the page table is responsible for translating virtual addresses to physical addresses. Whenever a page fault occurs or system calls such as mmap, munmap, or mprotect are executed, the kernel needs to perform lookup, insertion, deletion, or modification operations on the VMA.
[0003] In the current Linux kernel, the entire address space of a single process is protected by a global read-write semaphore, mmap_lock. This lock covers all VMA operations and page table operations. Any thread must acquire this lock before performing any memory management-related operations. Read operations can share the read lock, while write operations exclusively hold the write lock. Furthermore, a global tree is used to store all VMA information for the process, and finding a VMA requires traversing from the root node.
[0004] However, existing technologies have the following technical problems and drawbacks: First, global mmap_lock leads to severe lock contention. In multi-core scenarios, multiple threads of the same process share the same address space, competing for the same lock. Even when accessing completely disjoint memory address regions, operations must be serialized. Second, cache line contention for reading and writing semaphores is severe. The count and owner fields in the rw_semaphore structure are located in the same cache line. When multiple cores acquire read locks simultaneously, each core needs to atomically modify this cache line, triggering frequent cache line invalidation and transmission in the MESI protocol, resulting in a large amount of cache consistency traffic. Third, VMA lookup efficiency is low. The size of the global VMA tree grows linearly with the number of process mappings, resulting in long lookup paths and low cache hit rates for single-entry VMA entries. Summary of the Invention
[0005] Based on the above analysis, the embodiments of the present invention aim to provide a memory management method based on hierarchical VMA to solve the problems of existing global lock contention, cache line contention, low VMA lookup efficiency, and low cache hit rate.
[0006] This invention provides a memory management method based on hierarchical VMAs, comprising the following steps: When a request to operate on the virtual address space is received, the target address range involved in the operation request is obtained; Query the VMA fragment cache based on the target address range; If the VMA fragment cache misses the target VMA, acquire a range lock corresponding to at least one address partition that intersects with the target address range; under the protection of the range lock, perform VMA operations in the hierarchical VMA tree according to the target address range; otherwise, perform VMA operations according to the hit target VMA. Update the VMA fragment cache based on the results of the VMA operation.
[0007] Based on further improvements to the above method, the VMA fragment cache includes: an L1 cache for each CPU core and an L2 cache for each process; the L1 cache stores the most recently accessed VMA entries of the current CPU core and the process identifiers to which each entry belongs; the L2 cache is managed using an adaptive replacement caching algorithm and is used to store process-level VMA entries.
[0008] Based on the further improvement of the above method, address partitions are defined by page table descriptors. Each page table descriptor corresponds to a non-overlapping address partition and belongs to a page table level. All page table descriptors of different page table levels are organized in the same radix tree according to the address range they cover and the page table level they belong to. The key of the radix tree is obtained by adding the offset of the page table level to which the page table descriptor belongs to the partition index. The partition index is obtained by right-shifting the virtual address in the address partition corresponding to the page table descriptor by the number of bits corresponding to the page table level to which the page table descriptor belongs.
[0009] A further improvement to the above method involves acquiring a range lock corresponding to at least one address partition intersecting with the target address range, including: The target page table level is determined based on the preset range granularity, and the corresponding address partition size is obtained as the step size. Using the starting virtual address of the target address range as the current address, repeat the following search steps: Calculate the target key based on the current address and the target page table level, and search for the page table descriptor corresponding to the target key in the radix tree; if it does not exist, create a new page table descriptor and insert it into the radix tree; increment the current address by one step to become the next current address, and continue searching; until the current address is greater than or equal to the ending virtual address of the target address range, one or more page table descriptors intersecting with the address range are obtained; Acquire the corresponding spinlocks for one or more page table descriptors in sequence to form a range lock.
[0010] Based on a further improvement to the above method, one or more page table descriptors are sequentially acquired with corresponding spinlocks to form a range lock, including: Allocate a range lock object from the pre-allocated SLAB cache; for each obtained page table descriptor, call the spin lock acquisition attempt operation for that page table descriptor; if the acquisition attempt is successful, store the pointer of that page table descriptor in the locked list of the range lock object; if the spin lock acquisition attempt for any page table descriptor fails, traverse the locked list to release all acquired spin locks, return the range lock object to the SLAB cache, and return a failure status to trigger a retry of the operation request; if the spin lock acquisition attempts for all page table descriptors are successful, the range lock acquisition is successful.
[0011] Based on further improvements to the above method, the range lock object includes: a pointer to the memory descriptor of the current process, the starting address of the range lock, the ending address of the range lock, a locked list, the number of locked page table descriptors, an operation type flag, a delayed TLB refresh flag, and the starting and ending addresses of the delayed TLB refresh.
[0012] Based on further improvements to the above method, the hierarchical VMA tree is constructed in the following way: A red-black tree is allocated as a VMA subtree for each page table descriptor. The VMA subtree is used to store VMA segments belonging to the address partition corresponding to that page table descriptor. Page table descriptors of different page table levels are organized into a hierarchical structure according to the address range they cover. Each VMA segment has a standard VMA structure embedded as its first member, and contains a pointer to its own page table descriptor and the node structure of that VMA segment in the VMA subtree.
[0013] A further improvement to the above method involves performing VMA operations within a hierarchical VMA tree based on the target address range, including: When a VMA operation is a lookup operation, the starting virtual address of the target address range is used as the lookup target. Following the order from the lowest page table level to the highest page table level, the following lookup operations are performed sequentially in the page table descriptors corresponding to each page table level: obtain the lookup key based on the query target and the current page table level, and search for the corresponding page table descriptor in the radix tree; if not found, proceed to the next page table level; if found, search for the VMA segment containing the lookup target in the VMA subtree of that page table descriptor, until the target is found or all page table levels have been traversed.
[0014] Further improvements to the above method involve updating the VMA fragment cache based on the result of the VMA operation, including: If the result of the VMA operation is that the target VMA is found, then the target VMA is inserted into the L1 cache of the current CPU core and the L2 cache of the current process; when inserting into the L1 cache, the LFU cache eviction policy is used.
[0015] A further improvement to the above method involves querying the VMA fragment cache based on the target address range, including: Use the starting virtual address within the target address range as the target virtual address; Access the L1 cache using the current CPU core number as the index, traverse the VMA entries in the L1 cache. If the process ID of the current process is inconsistent with the process ID in the VMA entry in the L1 cache, skip the VMA entry; otherwise, determine whether the target virtual address is within the address range of the VMA entry. If so, a hit is found, increment the access count of the VMA entry, and return the corresponding VMA pointer as the target VMA. If the L1 cache misses, the L2 cache is queried. If the L2 cache hits, the VMA pointer corresponding to the hit VMA entry is returned as the target VMA; otherwise, the result of the miss is returned.
[0016] Compared with the prior art, the present invention can achieve at least one of the following beneficial effects: 1. Range locks are used instead of the global mmap lock in the traditional Linux kernel, which refines the lock granularity from the entire address space to a single address partition. This eliminates global lock contention and allows operations in non-overlapping address regions to be executed concurrently, significantly improving memory usage performance in multi-core scenarios.
[0017] 2. The cache line contention problem of traditional global read / write semaphores is decomposed into fine-grained spin locks for each address partition. Locks for different address partitions are located in different memory locations, avoiding multiple cores modifying the same cache line at the same time. At the same time, the range lock adopts a spin lock attempt acquisition strategy with extremely short lock holding time (microseconds). When it fails, it immediately retryes instead of waiting idly, avoiding long-term spinning and deadlocks, thereby significantly reducing cache consistency traffic and lock access latency.
[0018] 3. A hierarchical VMA tree was constructed, storing VMA fragments in page table descriptors at different page table levels according to their address range. During the search, the search starts from the bottom page table level and proceeds upwards. Taking advantage of the objective distribution characteristic that more than 90% of VMAs do not exceed 2MB, the average search level is only 1.12 levels, which significantly improves the VMA search efficiency and reduces the search latency.
[0019] 4. Through the synergistic effect of hierarchical VMA trees and multi-level VMA fragment caching, the VMA lookup speed is effectively improved, and the efficiency of page fault handling is accelerated.
[0020] In this invention, the above-described technical solutions can be combined with each other to achieve more preferred combinations. Other features and advantages of this invention will be set forth in the following description, and some advantages may become apparent from the description or be learned by practicing the invention. The objects and other advantages of this invention can be realized and obtained from what is particularly pointed out in the description and drawings. Attached Figure Description
[0021] The accompanying drawings are for illustrative purposes only and are not intended to limit the invention. Throughout the drawings, the same reference numerals denote the same parts. Figure 1 This is a flowchart of a memory management method based on hierarchical VMA in an embodiment of the present invention. Detailed Implementation
[0022] Preferred embodiments of the present invention will now be described in detail with reference to the accompanying drawings, which form part of this application and are used together with the embodiments of the present invention to illustrate the principles of the present invention, but are not intended to limit the scope of the present invention.
[0023] A specific embodiment of the present invention discloses a memory management method based on hierarchical VMAs, such as... Figure 1 As shown, it includes steps S1-S4.
[0024] S1. When a request to operate on the virtual address space is received, obtain the target address range involved in the operation request.
[0025] It should be noted that virtual address space operation requests include, but are not limited to: mmap system call requests, page fault handling requests, mprotect system call requests, brk system call requests, and munmap system call requests.
[0026] Different types of operation requests carry address information in different formats, so the methods for obtaining the target address range also differ.
[0027] Specifically, in the mmap system call scenario, when a process calls mmap to request memory mapping, the user program specifies parameters such as the desired starting address (usually 0 to indicate system selection), mapping length, and protection flags. In the mmap system call handler, the kernel needs to determine the actual virtual address region to be allocated. Typically, the kernel first searches for a free virtual address range; the starting address and length of this range constitute the target address range. If the user specifies a starting address and that address is available, the target address range is [specified starting address, specified starting address + length]. If the system automatically selects the region, the kernel searches for a free region in the process's virtual address space that meets the length requirement and determines its starting and ending addresses.
[0028] In page fault handling scenarios, when a process accesses a virtual address not mapped to physical memory, the CPU triggers a page fault, passing the virtual address that caused the fault to the kernel's page fault handler. This fault address is then the single virtual address that needs to be accessed. A page fault typically corresponds to a single memory access (read or write), and the address range involved can be considered as a page size (e.g., 4KB) interval starting from that address. However, this address is more often used as the key to look up the VMA. For consistency, this embodiment defines the target address range as a 1-byte range starting from this virtual address. In actual implementations, only the starting address can be recorded, implicitly setting the ending address to the starting address plus one.
[0029] In the context of the mprotect system call, when a process calls mprotect to modify the protection attributes of a memory region, it passes in the starting address and length, and the kernel determines the target address range based on these parameters.
[0030] In the context of the brk system call, the brk system call is used to adjust the end address of the process heap. The user program passes in a new heap top pointer. The kernel typically uses the range from the current heap top to the new heap top as the target address range for the adjustment.
[0031] In the munmap system call scenario, when a process calls munmap to release a mapped memory region, it passes in the starting address and length. The kernel determines the target address range based on these parameters, without needing to search for free regions separately.
[0032] By parsing different operation requests, the kernel obtains a defined target address range, represented by the starting virtual address vmstart and the ending virtual address vmend, denoted as [vmstart, vmend). This target address range will be used for subsequent cache lookups and range lock acquisition.
[0033] S2. Query the VMA fragment cache based on the target address range; if the VMA fragment cache hits the target VMA, then perform the VMA operation based on the target VMA.
[0034] In this embodiment, the VMA fragment cache includes: an L1 cache for each CPU core and an L2 cache for each process. The L1 cache stores the most recently accessed VMA entries of the current CPU core and the process identifiers to which each entry belongs. The L2 cache is managed using an adaptive replacement caching algorithm and is used to store process-level VMA entries. This design balances lookup speed and hit rate: the L1 cache has lock-free access and extremely fast response, making it suitable for caching the most frequently accessed VMA entries; the L2 cache has a larger capacity and a more intelligent algorithm, used to accommodate the working set of a process.
[0035] It should be noted that the L1 cache for each CPU core refers to defining an independent data structure (per_cpu_vma_cache) as the L1 cache for each CPU core. No locking is required when accessing it, and the data occupies the CPU cache line exclusively, completely eliminating false sharing and cache consistency overhead.
[0036] The number of VMA entries in the L1 cache of each CPU core is relatively small, such as 4 or 8. Each VMA entry stores the address range of the VMA (including the start address vmstart and the end address vmend), a pointer to the VMA, a pointer to the memory descriptor of the process to which it belongs, the process ID, and the access count. The VMA address range [vmstart, vmend) is used as the key, and the pointer to the VMA is used as the value. During a search, the target virtual address addr is input; if addr is located within the [vmstart, vmend) range, it is considered a hit.
[0037] This key-value structure allows the L1 cache to quickly determine a hit by simply comparing address ranges, without requiring additional hash calculations or tree traversals.
[0038] Each process's L2 cache is stored in the process's mm_struct structure. Each VMA entry in the L2 cache stores the address range of the VMA and a pointer to the VMA, also using the key-value format described above.
[0039] In this embodiment, the L2 cache is managed using the Adaptive Replacement Cache (ARC) algorithm. The ARC algorithm can dynamically adjust the preference for "Least Recently Used" (LRU) and "Least Frequently Used" (LFU) caches based on the runtime workload characteristics, thereby achieving an optimal balance between sequential scan and random revisit modes.
[0040] It should be noted that the ARC algorithm maintains four linked lists: T1 linked list stores VMA entries that have been accessed only once, sorted by the most recent access time; T2 linked list stores VMA entries that have been accessed at least twice, sorted by the most recent access time; B1 linked list stores the metadata of VMA entries evicted from T1, serving as a ghost list; B2 linked list stores the metadata of VMA entries evicted from T2. That is, B1 and B2 only store the hash signature of the key of the evicted VMA entry, without retaining the VMA pointer, serving as a ghost list.
[0041] set up This is the total capacity of the L2 cache (i.e., the upper limit of the sum of the number of VMA entries in T1 and T2). The target capacity of linked list T1 ( Then the capacity of linked list T2 is... .
[0042] This embodiment describes the parameters. The update method has been improved to better suit the characteristics of the VMA access mode.
[0043] Specifically, when the hit VMA entry is located in B1 (i.e., the entry most recently evicted from T1 is accessed again), the target capacity in the T1 linked list is updated using the following formula: , in, and These represent the target capacities of linked list T1 before and after the update, respectively. and These represent the entry capacities of linked lists B1 and B2, respectively.
[0044] The meaning of this formula is: if there are many ghost entries in B1, it indicates that the capacity of T1 may be too small, causing a large number of entries that are only accessed once to be prematurely eliminated. Therefore, the target capacity of the T1 linked list needs to be increased. ,ensure No more than the total capacity .
[0045] When the hit VMA entry is located in B2 (i.e., the entry most recently evicted from T2 is accessed again), update the target capacity of the T1 linked list using the following formula: .
[0046] The meaning of this formula is: if there are many ghost entries in B2, it means that frequently accessed entries (which should be stored in T2) have been evicted, and it may be necessary to reduce the target capacity of the T1 linked list. This frees up more space for T2; while ensuring Not less than 0.
[0047] When the hit VMA entry is located in T1 or T2: Leave it unchanged, only adjust the position of the entry in the linked list (move it to the head).
[0048] This dynamic adjustment mechanism allows the L2 cache to quickly detect changes in workload. For example, when an application switches from sequential scans (many VMAs accessed only once) to random revisits (few frequently accessed VMAs), the number of B2 hits will increase. The T2 capacity is automatically reduced and increased, thus keeping hot VMAs in the cache for a long time.
[0049] Furthermore, the VMA fragment cache is queried based on the target address range, including: Use the starting virtual address within the target address range as the target virtual address; Access the L1 cache (per_cpu_vma_cache) using the current CPU core number as the index, obtain the process ID of the current process, traverse the VMA entries in the L1 cache. If the process ID of the current process does not match the process ID in the VMA entry in the L1 cache, skip the VMA entry; otherwise, determine whether the target virtual address is within the address range of the VMA entry. If so, a hit is found, increment the access count of the VMA entry, and return the corresponding VMA pointer as the target VMA. If the L1 cache misses, the L2 cache is queried. If the L2 cache hits, the VMA pointer corresponding to the hit VMA entry is returned as the target VMA and inserted into the L1 cache; otherwise, the result of the miss is returned.
[0050] The query L2 cache includes: Get the memory descriptor of the current process and retrieve the L2 cache structure from the memory descriptor; search for the VMA entry corresponding to the target virtual address in the L2 cache structure; if a match is found, return the corresponding VMA pointer and insert the VMA into the L1 cache; if the L1 cache is full, evict the entry with the least access count; if a miss is found, return a null pointer, indicating that the cache was not hit, and proceed to step S3.
[0051] The process of finding the VMA entry corresponding to the target virtual address in the L2 cache structure includes: based on the target virtual address, searching for a matching VMA entry in the T1 and T2 linked lists by comparing the address range (i.e., whether the target virtual address is located between the start and end addresses stored in the linked list node); if a match is found in T1 or T2, the matched VMA entry is moved to the head of the linked list and the VMA pointer is returned; if a match is found in B1 or B2 (a ghost hit), the parameters are updated according to the aforementioned formula. The system then removes the hit VMA entry from the ghost list and re-inserts it into T1 or T2 (specifically, inserting into T2 when B1 hits and into T1 when B2 hits), and then returns the VMA pointer obtained from the VMA entry as the target VMA.
[0052] Compared with the prior art, the VMA cache entries in this embodiment use a key-value structure, which makes the cache lookup logic unified and efficient, and easy to implement and maintain; the ARC parameter update formula is dynamically adjusted by using the capacity ratio of B1 and B2, which is more sensitive to sudden changes in workload and facilitates the improvement of hit rate.
[0053] S3. If the VMA fragment cache does not hit the target VMA, acquire a range lock corresponding to at least one address partition that intersects with the target address range; under the protection of the range lock, perform VMA operations according to the hierarchical VMA tree of the target address range; otherwise, perform VMA operations according to the hit target VMA.
[0054] It should be noted that this embodiment divides the entire virtual address space into multiple fixed-size address partitions. Each address partition corresponds to a Page Table Descriptor (PTD). The PTD is used not only to manage hardware page tables but also to manage VMA segments within the range of that address partition. Each page table descriptor corresponds to a fixed-size address partition, and the size of the address partition is determined by the page table level to which the page table descriptor belongs. The granularity of each page table level includes: PT level, with a range granularity of 2MB: Each page table descriptor (PTD) covers 2MB of virtual address space (corresponding to 512 4KB pages). In this embodiment, considering that most VMA management intervals are less than 2MB, the preset range granularity is 2MB, that is, the default page table level is the PT level. PMD level, with a granularity of 1GB: each page table descriptor (PTD) covers 1GB of virtual address space (corresponding to 512 2MB blocks); suitable for very large memory mapping, reducing the number of PTDs; PUD hierarchy with a granular range of 512GB: each page table descriptor (PTD) covers a 512GB virtual address space; suitable for large memory, low concurrency scenarios; PGD level, with a granularity of 256TB: each page table descriptor (PTD) covers the entire process address space; only used in extreme cases.
[0055] In other words, each page table descriptor corresponds to a non-overlapping address partition and belongs to a page table level; within the same page table level, all address partitions are the same size; however, the address partition sizes differ between different levels.
[0056] Each page table descriptor contains the following key fields: a spinlock `ptd_lock`, used to protect all data within the PTD and implement fine-grained concurrency control; a VMA subtree root node `vma_tree`, storing all VMA segments belonging to the address partition corresponding to the current PTD, sorted by the starting virtual address of the VMA; a page table level, used to record the page table level (PT / PMD / PUD / PGD) corresponding to the page table descriptor; and descriptor status flags `ptd_flags`, which are unsigned long integers, including: an active status flag (the PTD is in use) and a dirty status flag (the VMA or page table within the PTD has been modified and may need to be reverted). (Write or refresh) or lock status flag (whether the PTD is currently locked by a range lock); VMA segment list vma_list, the head of a doubly linked list, used to link all VMA segments within the address partition, facilitating traversal operations (e.g., batch release of VMAs when a process exits); VMA segment count vma_count; access count access_count, used to record the number of times the address partition has been accessed, which can be used for statistics or adaptive optimization; range lock list node list, used to attach the PTD to the locked list of the range lock object when acquiring the range lock, facilitating subsequent unified operations on page table descriptors within this range, such as releasing the range lock.
[0057] All page table descriptors at different page table levels are organized in the same radix tree (i.e., the global radix tree) according to the address range they cover and the page table level they belong to. The key of each page table descriptor in the radix tree is obtained by adding the offset of the page table level to which the page table descriptor belongs to the partition index. The partition index is obtained by right-shifting the virtual address within the address partition corresponding to the page table descriptor by the number of bits corresponding to the page table level to which the page table descriptor belongs, as shown in the formula below: , in, The key of the page table descriptor in the radix tree. It can be any virtual address of the address partition corresponding to the page table descriptor; and They are shift right and shift left, respectively; This is the offset at the page table level. The bit width of the virtual address, such as 48 bits or 57 bits actually used in a 64-bit system, is used to ensure that the page table identifiers of different page table levels have non-overlapping key ranges in the radix tree. The page table level to which the page table descriptor belongs. The corresponding bit widths are as follows: PT level has 21 bits, PMD level has 30 bits, PUD level has 39 bits, and PGD level is determined based on the virtual address width.
[0058] This embodiment uses a design that requires only one radix tree to index page table descriptors at all page table levels.
[0059] When the VMA fragment cache in step S2 misses the target VMA, based on the target address range [vmstart, vmend) parsed from the operation request, it is necessary to determine all address partitions intersecting with this range, i.e., to find all page table descriptors that need to be locked, including: First, the target page table level is determined according to the preset range granularity (PT level is used by default), and the address partition size corresponding to the target page table level is used as the step size. Using the starting virtual address vmstart of the target address range as the current address, repeat the following search steps: Calculate the target key based on the current address and the target page table level; search for the page table descriptor corresponding to the target key in the radix tree; if it does not exist, create a new page table descriptor and insert it into the radix tree; increment the current address by one step to become the next current address and continue searching; until the current address is greater than or equal to the ending virtual address vmend of the target address range, one or more page table descriptors intersecting with the address range are obtained, and the union of the address partitions of these page table descriptors completely covers the target address range.
[0060] For example, suppose the target address range is [0x1000, 0x5000), traversed at the PT layer granularity (2MB partitions). The starting address of each 2MB partition is 2MB aligned, such as [0x000000, 0x200000), [0x200000, 0x400000), etc. 0x1000 belongs to partition [0, 0x200000), and 0x5000 also belongs to the same partition, so only one PTD is involved. If the address range spans multiple partitions (e.g., [0x1000, 0x300000)), then two partitions will be involved, corresponding to two PTDs.
[0061] It should be noted that a range lock is a collective lock on a set of spin locks for a group of page table descriptors. For all involved page table descriptors, the system attempts to acquire their spin locks sequentially; if all attempts succeed, the range lock is successfully acquired. If any attempt fails, all acquired locks are released, a failure status is returned, and a full retry of the operation request is triggered.
[0062] Specifically, the corresponding spinlocks are acquired sequentially for one or more page table descriptors to form a range lock, including: Allocate a range lock object `range_lock` from the pre-allocated SLAB cache (Slab Allocation Cache). This object includes: a pointer to the memory descriptor of the current process, the start address of the range lock, the end address of the range lock, a locked list, the number of locked page table descriptors, an operation type flag (read or write), a delayed TLB refresh flag, and the start and end addresses of the delayed TLB refresh. Initialize the locked list to empty and the number of locked page table descriptors to 0; initialize the start and end addresses of the range lock according to the target address range.
[0063] Furthermore, for each obtained page table descriptor, sort them in ascending address order and call the spin lock acquisition operation (spin_trylock) for that page table descriptor. If the acquisition attempt is successful, the pointer of the page table descriptor is stored in the locked list of the range lock object. If the spin lock acquisition attempt for any page table descriptor fails (indicating that the spin lock of that PTD is already held by another thread), the locked list is traversed to release all acquired spin locks, the range lock object is returned to the SLAB cache, and a failure status (e.g., -EAGAIN) is returned to trigger a retry of the operation request (re-starting execution from step S1 to obtain the target address range). If the spin lock acquisition attempts for all page table descriptors are successful, the range lock is successfully acquired, and subsequent VMA operations can be safely executed under the protection of this range lock.
[0064] This embodiment employs a "try-fail-retry" strategy, and the spinlock holding time for each page table descriptor is extremely short (typically on the order of microseconds), avoiding the long CPU idle time that may result from traditional spinlocks. All threads acquire the lock in ascending address order, effectively preventing deadlocks.
[0065] For read-only operations (such as page fault lookup VMA), spinlocks can be replaced with read-write locks to allow multiple read operations to concurrently access the same page table descriptor. This embodiment uses spinlocks for simplicity.
[0066] It should be noted that in scenarios where multiple threads concurrently access the virtual address space, the acquisition behavior of range locks depends on whether the target address ranges operated on by each thread overlap or intersect. When the target address ranges operated on by multiple threads are located in non-overlapping address partitions, and the page table descriptors involved are different, each thread can acquire the spin lock of its own page table descriptor simultaneously, thereby achieving fully parallel execution.
[0067] When multiple threads simultaneously request address ranges that fall within the same address partition, regardless of whether these address ranges overlap, these threads will compete for the spinlock of the same page table descriptor. In this situation, the range locking mechanism cannot allow these operations to be fully parallelized; instead, they must be executed serially according to the order in which the locks are acquired: only after the previous operation requests the release of the range lock can the next operation request begin acquiring the range lock. Compared to the complete serialization of the entire address space caused by the global read / write semaphore mmap_lock in traditional Linux, the serialization range in this embodiment is precisely limited to the single address partition where the contention occurs. Operations in other address partitions can still be fully parallelized, thereby significantly improving multi-core concurrency performance.
[0068] For example, when two threads perform mmap operations on different addresses (such as 0x1000 and 0x3000) within the same address partition, since both involve the same page table descriptor, the second thread will fail (or be blocked, depending on the implementation strategy) when trying to acquire the spinlock of that page table descriptor, and must wait for the first thread to release the spinlock of that page table descriptor before it can continue. However, if a third thread operates on an address within another address partition at the same time, it will be completely unaffected and can execute after acquiring its own page table descriptor.
[0069] When a multi-level VMA cache hit occurs, the type of operation request is first determined. For read-only operations (such as VMA permission checks in page fault exceptions), the information in the VMA fragment returned by the cache is used directly for processing, without acquiring any locks, because read-only operations do not modify the VMA subtree structure and can be performed concurrently safely. For write operations (such as mprotect, munmap, mmap, etc., which may modify VMA attributes or structure), although the VMA fragment has been obtained from the cache, a range lock on the page table descriptor to which the VMA fragment belongs still needs to be acquired to ensure the atomicity and concurrency safety of the modification operation. At this time, based on the pointer to the page table descriptor stored in the hit VMA fragment, the spin lock and the root node of the VMA subtree in the page table descriptor are accessed to locate the complete VMA subtree; at the same time, a range lock object is created, the pointer of the page table descriptor is added to the locked list, and an attempt is made to acquire its spin lock to form a range lock containing the page table descriptor.
[0070] After acquiring the range lock for both miss and hit scenarios, the specific operation is performed in the hierarchical VMA tree under the protection of the range lock, based on the target address range.
[0071] It should be noted that the hierarchical VMA tree consists of multiple VMA subtrees distributed according to the page table hierarchy, and is constructed in the following way: A red-black tree is allocated as the VMA subtree for each page table descriptor, with an average of only 10-20 nodes. The VMA subtree stores VMA segments belonging to the address partition corresponding to that page table descriptor; page table descriptors of different page table levels (PGD, PUD, PMD, PT) are organized into a hierarchical structure according to the address range they cover. Each VMA segment (vma_segment) embeds a standard VMA structure (vm_area_struct) as its first member, facilitating its transfer to other kernel modules without modifying existing interfaces. Through zero-overhead macro conversion, it is compatible with existing VMA operation interfaces. The VMA segment also includes a pointer to its parent page table descriptor, the node structure of the VMA segment in the VMA subtree, and its storage level.
[0072] VMA fragments automatically select their storage level based on the address range they cover: if the address range does not cross the 2MB boundary (i.e., the start and end addresses belong to the same 2MB block), the VMA fragment is stored in the VMA subtree of the page table descriptor in the PT layer; if it does not cross the 1GB boundary, it is stored in the PMD layer; if it does not cross the 512GB boundary, it is stored in the PUD layer; otherwise, it is stored in the PGD layer. This strategy of automatically selecting the storage level based on address range boundaries ensures that 90% of small VMAs (≤2MB) are stored in the VMA subtree of the PT layer, 8% of medium VMAs (2MB~1GB) are stored in the VMA subtree of the PMD layer, and 2% of large VMAs (above 1GB) are stored in higher-level VMA subtrees, forming a logically hierarchical VMA tree. This hierarchical storage allows for searching from the bottom up, leveraging the high proportion of small VMAs for rapid hits and extremely high search efficiency.
[0073] The following sections describe VMA operations such as search, insert, delete, merge, and split.
[0074] (1) The lookup operation is mainly used in scenarios such as page faults or mprotect where the VMA needs to be located. The lookup operation takes the starting virtual address of the target address range as the search target and finds the VMA segment containing the search target in the hierarchical VMA tree.
[0075] Specifically, following the order from the lowest page table level to the highest page table level, the following lookup operation is performed sequentially in the page table descriptor corresponding to each page table level: The lookup key is obtained based on the query target and the current page table level. The corresponding page table descriptor is searched in the radix tree. If not found, the process proceeds to the next page table level. If found, the VMA segment containing the search target is searched in the VMA subtree of that page table descriptor until it is found or all page table levels have been traversed. If it is still not found after traversing all page table levels, NULL is returned, triggering an error message.
[0076] Specifically, the search for the VMA segment containing the target value is performed within the VMA subtree of the page table descriptor, including: Using the starting address of the VMA segment as the sort key, find the largest node whose starting address is less than or equal to the target. If the target is less than the ending address of the node, it is considered a match and the VMA segment in the node is returned; otherwise, it means that it was not found.
[0077] Since over 90% of VMAs are no larger than 2MB, lookup operations can usually return at the PT level, with an average lookup level of only 1.12 (1.12 times = 1×90% + 2×8% + 3×2% + 4×0%), which significantly shortens the lookup path compared to the traditional global VMA tree.
[0078] (2) Insertion operations are used in scenarios such as mmap or brk that require the creation of new VMAs.
[0079] The insertion operation adds a new VMA segment to the VMA subtree of the appropriate page table descriptor. Key steps include: selecting the storage level (i.e., the page table level to be stored), finding or creating the PTD, performing the insertion, and handling adjacent merges.
[0080] Specifically, the storage level is first determined based on the start address (newstart) and end address (newend) of the VMA to be inserted, using a bottom-up decision-making order, including: The start address (newstart) and end address (newend-1) are decremented by one and shifted right by 21 bits (because 2MB corresponds to 21 bits), resulting in two indices at the PT level. If the two indices at the PT level are equal, it means that the VMA to be inserted does not cross the 2MB boundary, and the PT level is selected as the storage level. If the two indexes at the PT level are not equal, the start address (newstart) and end address (newend-1) are decremented by one and shifted right by 30 bits respectively to obtain the two indexes at the PMD level. If the two indexes at the PMD level are equal, it means that the VMA to be inserted has not crossed the 1GB boundary, and the PMD level is selected as the storage level. If the two indexes at the PMD level are not equal, the start address (newstart) and end address are decremented by one (newend-1) and shifted right by 39 bits respectively to obtain the two indexes at the PUD level. If the two indexes at the PUD level are equal, it means that the VMA to be inserted has not crossed the 512GB boundary, and the PUD level is selected as the storage level. Otherwise, select the PGD level as the storage level.
[0081] After determining the storage page table hierarchy, calculate the key in the global radix tree based on the starting address of the VMA to be inserted, and obtain or create the corresponding page table descriptor PTD.
[0082] Then, the VMA to be inserted is encapsulated as a VMA segment (vma_segment). This segment embeds a complete standard VMA structure as its first member and contains a pointer to its respective page table descriptor, the root node of the VMA subtree, and a linked list node. The VMA segment is inserted into the VMA subtree of the page table descriptor, added to the VMA segment linked list vma_list of the page table descriptor, and the number of VMA segments vma_count in the PTD is updated.
[0083] After insertion, attempt to merge with adjacent VMA segments (see the merging algorithm below). If the merge is successful, delete the merged adjacent segments; update the number of VMA segments vma_count in the PTD, and the total number of VMA segments in the process (total_vma_seg_count of the memory descriptor mm_struct of the current process).
[0084] (3) The delete operation is used for removal during munmap or VMA merging.
[0085] The delete operation removes the specified VMA segment from the hierarchical VMA tree and releases empty page table descriptors if necessary.
[0086] First, based on the passed target address or pointer to the VMA segment, search for the specified VMA segment and its corresponding page table descriptor in the hierarchical VMA tree. If not found, return -EINVAL, indicating that the passed parameter is invalid.
[0087] Then, the VMA segment is removed from the VMA subtree and VMA segment list of the found page table descriptor PTD, the page table mapping associated with the VMA segment is cleaned up (TLB is refreshed), and the number of VMA segments in PTD is updated.
[0088] If the VMA fragment count of a PTD is updated to 0, the page table descriptor PTD is removed from the global radix tree, and the memory it occupies is released.
[0089] Finally, the VMA fragment is returned to the SLAB cache.
[0090] (4) The merge operation is automatically triggered after inserting a new VMA fragment or modifying VMA attributes. If the address ranges of adjacent VMA fragments are continuous and all attributes (permissions, mapping files, offsets, etc.) are exactly the same, they should be merged into one VMA to reduce the number of VMA fragments and improve the efficiency of subsequent searches.
[0091] First, sort by starting address and obtain the predecessor and successor segments of the current VMA segment in the VMA subtree.
[0092] Further, the predecessor segment is checked, including: if the end address of the predecessor segment is equal to the start address of the current VMA segment, and all attributes of the two (flags vm_flags, access permissions vm_page_prot, mapping file vm_file, offset vm_pgoff) are exactly the same, then the start address of the current VMA segment is expanded to the start address of the predecessor segment, and the predecessor segment is removed from the VMA subtree and the VMA segment list, and its memory is released.
[0093] Further, the successor segment is checked, including: if the end address of the current VMA segment is equal to the start address of the successor segment and the attributes are exactly the same, then the end address of the current VMA segment is extended to the end address of the successor segment, the successor segment is deleted from the VMA subtree and the VMA segment linked list, and its memory is released.
[0094] Since the address range of the merged VMA may increase, the storage level is re-determined based on the address range of the merged VMA. If the new storage level is different from the original storage level, the merged VMA segment is deleted from the original page table descriptor and then inserted into the page table descriptor corresponding to the new storage level. The pointer of the page table descriptor in the corresponding VMA segment is also updated.
[0095] (5) The splitting operation is to split the original VMA segment into two or more segments when certain operation requests (such as mprotect, munmap, mremap) only affect a part of the VMA.
[0096] For example, when calling `mprotect(addrf, len, prot)` to modify the permissions of the region `[addrf, addrf+len)`, if the `[addrf, addrf+len)` region does not completely cover the VMA containing `addrf`, and `addrf` is inside a VMA, then `addrf` is the split point, and the original VMA is split into left and right parts at `addrf`; if `addrf+len` is inside a VMA, then the split is performed at `addrf+len`. When calling `munmap(addrf, len)` to release a segment of memory (not the entire VMA), if `addrf` is greater than the start address of a VMA but less than its end address, then the split is performed at `addrf`; if `addrf+len` falls inside a VMA, then the split is performed at `addrf+len`. When calling `mremap()` to remap a region, if the new address overlaps with the original address range or needs to be truncated, a split point must also be determined for splitting.
[0097] First, the segmentation point of the original VMA segment is determined based on the boundary of the operation request, and the page table descriptor to which the original VMA segment belongs, as well as its address range, attributes, and other metadata, are recorded.
[0098] Then, the original VMA segments are removed from the VMA subtree and VMA segment list of the original page table descriptor, and the number of VMA segments in the original page table descriptor and the total number of VMA segments in the process are updated.
[0099] Next, two new VMA segments are created. The left segment overwrites the original start address to the split point, and the right segment overwrites the split point to the original end address. The attributes of the left and right segments are copied from the original VMA. If the original VMA has file mappings, get_file is called to increment the file reference count.
[0100] Furthermore, the page table levels stored for the left and right segments are determined based on their respective address ranges (they may differ; for example, the left segment may remain at the PT level while the right segment may cross the boundary into the PMD level). The corresponding page table descriptors are then obtained or created. The left and right segments are inserted into their VMA subtrees and VMA segment lists, and the number of VMA segments in the corresponding page table descriptors and the total number of VMA segments in the process are updated.
[0101] If the number of VMA segments of the original page table descriptor is updated to 0, the original page table descriptor is removed from the global radix tree and the memory it occupies is released.
[0102] It should be noted that after the segmentation, due to the smaller address range, the original VMA cache entries may still be retained in the original multi-level cache. Therefore, it is necessary to actively delete the original VMA entries from the L1 and L2 caches and insert the newly generated VMA fragments into the cache.
[0103] (6) Modification operations are automatically triggered when the access permissions of the VMA are modified, such as calling mprotect to change from read-only to write.
[0104] Taking changing the access permissions of all VMAs within a specified address range [mstart, mend) as an example, firstly, based on the specified address range, all affected VMA segments are located through a lookup operation. For VMAs that are partially covered, a segmentation operation needs to be performed first to align the modification range with the VMA boundaries.
[0105] Specifically, if `mstart` is greater than the start address `bstart` of the first affected segment and less than its end address `bend`, it means the starting boundary of the specified range is inside the first affected segment. In this case, the split operation is called to divide the segment into two parts at `mstart`, and the right part (overriding `[mstart, bend)`) is retained as the modified segment. Similarly, if `mend` is less than the end address `lend` of the last affected segment and greater than its start address `lstart`, the split operation is called to divide the segment at `mend`, and the left part (overriding `[lstart, mend)`) is retained as the modified segment. After the above boundary alignment processing, all modified segments fall completely within the range `[start, end)`.
[0106] Then, for each modified fragment, update its vm_flags and vm_page_prot fields, simultaneously modify the corresponding page table entry permission bits, and record the TLB range that needs to be refreshed in the start and end addresses of the delayed TLB refresh of the range lock object for subsequent unified refresh.
[0107] After the modifications are completed, identify whether there are adjacent modified fragments with the same attributes. If so, perform a merge operation to reduce fragmentation.
[0108] It should be noted that all the above VMA operations are performed under the protection of range locks, that is, the spin locks of the relevant page table descriptors are held throughout the operation. This ensures the consistency of the VMA tree structure and avoids the serialization bottleneck caused by traditional global locks.
[0109] S4. Update the VMA fragment cache based on the result of the VMA operation.
[0110] It's important to note that after completing a VMA operation (e.g., successfully finding a VMA, or inserting, deleting, or modifying a VMA), the result needs to be updated in the VMA fragment cache to improve the hit rate of subsequent accesses. This update can be performed before or after releasing the range lock, but to ensure consistency between the cached content and the hierarchical VMA tree, it is usually performed before releasing the range lock (because the lock is still held at this time, and the data is stable).
[0111] Update the VMA fragment cache based on the results of the VMA operation, including: For the lookup operation, if the target VMA is found, it is inserted into the L1 cache of the current CPU core and the L2 cache of the current process. When inserting into the L1 cache, the LFU (Least Frequently Used) cache eviction policy is used; that is, if the L1 cache is full, the VMA entry with the fewest access counts is evicted. The key of the inserted VMA entry is the start and end virtual addresses of the target VMA, and the value is a VMA pointer. When inserting into the L2 cache, the ARC (Archived Access Count) algorithm is followed, including: inserting the target VMA at the head of the T1 linked list; if the length of T1 exceeds the current capacity of its target VMA... If the length of the T1 linked list exceeds the preset limit, then the VMA entry at the end of the B1 linked list is discarded; if the length of the T2 linked list exceeds its current target capacity... If so, move the VMA entry at the end of T2 to the B2 linked list and discard the VMA entry at the end of B2.
[0112] For insertion operations, the new VMA segment is also inserted into the L1 cache of the current CPU core and the L2 cache of the current process.
[0113] For deletion operations, the specified VMA entry is removed from the L1 cache of the current CPU core and the L2 cache of the current process; the L1 cache of other CPU cores is evicted using the LFU cache eviction policy (because the deleted VMA will no longer be accessed).
[0114] For modification operations, if the VMA's attributes change, first check if the VMA entry exists in the L1 cache of the current CPU core and the L2 cache of the current process. If it exists, update the corresponding attribute fields in the VMA entry to maintain cache correctness. If it does not exist, no additional operation is required, because subsequent accesses will execute step S3 to reload and cache from the hierarchical VMA tree due to a cache miss.
[0115] For merge and split operations, the original VMA cache entry is deleted, and the merged VMA fragment or the split left and right VMA fragments are inserted into the L1 cache of the current CPU and the L2 cache of the current process.
[0116] It should be noted that after all VMA operations and cache updates are completed, the range lock is released, including: traversing the locked list in reverse order of locking and releasing the spin locks one by one; and returning the range lock object to the SLAB cache.
[0117] Specifically, before releasing the lock, the delayed TLB refresh flag in the range lock object is checked. If the flag is true, a TLB refresh operation is performed on the virtual address range recorded between the start and end addresses of the delayed TLB refresh. This invalidates the TLBs corresponding to multiple page table modifications and merges them into a single refresh, thereby significantly reducing the TLB refresh overhead.
[0118] During release, the locked list of the range lock objects is traversed in reverse order of locking, and the spinlock release operation is called for each page table descriptor.
[0119] Finally, the range lock object is returned to the SLAB cache for later use.
[0120] Preferably, the background monitoring thread periodically collects statistical information such as cache hit rate, B1 / B2 hit ratio, and prefetch hit rate, and dynamically adjusts the cache capacity, prefetch distance, and replacement strategy (ARC / MRU) according to preset rules.
[0121] Specifically, dynamically adjusting the cache size includes: If the L1 cache hit rate remains below the preset minimum hit rate threshold, such as 30%, it indicates that the current L1 cache capacity is insufficient to accommodate hot VMAs. In this case, the L1 cache capacity is automatically increased, up to a maximum of 8 entries. Conversely, if the L2 cache hit rate is higher than the preset maximum hit rate threshold, such as 80%, and the L1 cache capacity has not yet reached its minimum value, it indicates that the L1 cache is redundant. The L1 cache capacity is appropriately reduced to save memory, down to a minimum of 4 entries. Increasing or decreasing the L1 cache capacity is achieved by reallocating the cache array for each CPU core and migrating the original entries to the new array.
[0122] If the L2 cache hit rate remains below the preset minimum hit rate threshold, and the VMA tree lookup latency after a miss is higher than the preset latency threshold (e.g., 500 nanoseconds, or more than 1.5 times the historical average latency), the L2 cache capacity will be automatically increased. This includes: reallocating a larger cache space, migrating existing cached VMA entries to the new space, and updating the total capacity parameter c (e.g., increasing by 50% or doubling it). At the same time, the target capacity of the parameter T1 linked list will be adjusted proportionally to maintain the relative ratio of T1 and T2.
[0123] It should be noted that dynamically adjusting the prefetch distance is determined by analyzing the address sequence of memory access requests to identify the access patterns of the current workload, including: When the virtual addresses of multiple consecutive memory access requests increase linearly (e.g., each time by a page size of 4KB) without significant backswings, it is determined to be a sequential access pattern. This pattern is common in scenarios such as large file reading and array traversal. In sequential access mode, spatial locality is very pronounced; the address following the current accessed address is highly likely to be accessed later. In this case, increasing the prefetch distance (e.g., setting it to 4) means preloading the four VMA entries following the target VMA into the L2 cache. When multiple consecutive memory access requests exhibit jumps in virtual addresses, with large and unpredictable differences between adjacent accesses, and a consistently low cache hit rate, it is identified as random access mode. This mode is commonly seen in scenarios such as pointer chasing and hash table traversal. In random access mode, prefetching is often ineffective or even wastes cache space. In such cases, the prefetch distance should be set to 0 (disable prefetching) or 1 (do not perform additional prefetching).
[0124] The dynamic adjustment of the L2 cache replacement algorithm strategy is determined by simultaneously monitoring access patterns and L2 cache efficiency indices, including: When the efficiency index of the L2 cache is below 0.5, it indicates that the current caching strategy is not effective. At this time, regardless of the access mode, the L2 cache replacement strategy should be forcibly switched to the ARC algorithm, and access mode-based strategy switching should be temporarily disabled until the efficiency index recovers to above 0.5. When the efficiency index of the L2 cache is within the normal range (≥0.5), the strategy is further dynamically adjusted based on the access pattern: if a sequential access pattern is detected (multiple consecutive virtual addresses linearly increasing), the replacement strategy is temporarily switched to MRU (Most Recently Used), because newer entries in a sequential scan are less likely to be accessed again, and MRU can more promptly evict older entries; if a random access pattern is detected (address jumping and low hit rate), the algorithm is switched back to ARC to balance recent and frequent accesses. When the access pattern changes again, the strategy switches accordingly, but once the efficiency index drops below the threshold, ARC intervenes first and overrides any pattern-driven switch. Through this hierarchical decision-making, the caching strategy is made adaptable to the workload, while avoiding the continuous use of suboptimal strategies due to pattern misjudgment when efficiency is low.
[0125] In this embodiment, the efficiency index = (L2 cache hit rate × average saved latency) / total overhead, where average saved latency refers to the average time saved by accessing the hierarchical VMA tree when the L2 cache hit is compared to when the L2 cache miss is missed, and total overhead refers to the average time for performing L2 cache lookups (including hits and misses).
[0126] It should be noted that the range lock mode in this embodiment can be flexibly enabled through kernel startup parameters or runtime settings. There is no need to replace the system call entry point. Simply add a judgment inside the traditional memory management function to achieve a smooth switch between the traditional mode and the range lock mode.
[0127] Specifically, a global configuration variable (e.g., `range_lock_enabled`) is added to the kernel. This variable can be set at startup via kernel command-line arguments (e.g., `range_lock=on`) or dynamically modified at runtime via ` / proc / sys` or the `sysctl` interface. At the entry points of traditional memory management functions (such as `mmap`, page fault exception, `mprotect`, `munmap`, and `brk`), a conditional branch is added: if `range_lock_enabled` is true, the system is in range lock mode and executes the method described in this embodiment; otherwise, it is in traditional mode and executes the original kernel operation path.
[0128] Furthermore, in the traditional Linux kernel, before modifying a VMA, vma_start_write(vma) must be called to acquire the write lock of the VMA, and vma_end_write(vma) must be called after the operation is completed. However, in the range lock mode of this embodiment, since the entire operation is protected by the range lock, it is not necessary to acquire the lock (mmap_lock or per-VMA lock) in the traditional Linux kernel when performing VMA operations.
[0129] Specifically, this embodiment adds a conditional check to the vma_start_write macro or inline function: by checking the local flag of the current thread or the global configuration variable range_lock_enabled, it determines whether the current thread is under range lock protection. If so, it returns directly without performing any locking action. Similarly, vma_end_write also performs a no-operation.
[0130] Through the above design, this embodiment flexibly selects the traditional mode or the range lock mode according to the actual deployment scenario, realizing smooth migration and low-risk deployment, while ensuring compatibility with existing kernel modules and drivers.
[0131] The following scenario uses the example of four threads in the same process simultaneously calling mmap to allocate memory to further describe the overall processing flow of this embodiment.
[0132] In this scenario, the address ranges operated by the four threads do not overlap and are located in different address partitions. The page size is 4KB (0x1000), while the address partition size granularity is configured to 2MB (PT level), as detailed in Table 1.
[0133] Table 1. Information on memory allocation by four threads simultaneously calling mmap.
[0134] The execution process is as follows: ① Determine the target address range based on the operation request: Based on the operation request of each thread, the corresponding target address range is obtained. For example, when thread 1 calls mmap(0x1000, 4096), the kernel resolves the starting address start=0x1000 and the ending address end=0x2000, with an address range of [0x1000, 0x2000).
[0135] ② Query VMA fragment cache: Each thread queries the L1 cache of the current CPU core based on its own address range. Since this is the first access, the L1 cache is empty, resulting in a cache miss. The thread then queries the L2 cache of the current process, which also fails to find a cache miss, and proceeds to the next step.
[0136] ③ Determine the target address partition and obtain the page table descriptor: According to the default configuration, the current address range granularity is 2MB, which is the PT level. Each thread generates its own radix tree key based on the starting address of its address range, the bit width (2^1) and offset corresponding to the PT level (e.g., 0 << 48). For example, thread 1's radix tree key1 = (0 << 48) + (0x1000 >> 2^1) and searches for the page table descriptor corresponding to the radix tree key in the global radix tree. Since this is the first time accessing each address partition, the page table descriptor does not exist. Therefore, a new page table descriptor structure is created (memory is allocated, spinlocks, VMA subtrees, VMA linked lists, etc. are initialized), and it is inserted into the radix tree. In the end, each thread only involves one page table descriptor, corresponding to its own address partition, and the four page table descriptors are all different.
[0137] ④ Acquire the range lock: Allocate a range lock object to each thread and initialize it according to its respective address range; attempt to acquire the spin lock of the page table descriptor corresponding to each thread. Since the spin locks of the four page table descriptors are independent, all four threads successfully acquire the lock without waiting. Store the pointer of each page table descriptor in the locked list of the corresponding range lock object, and increment the number of locked page table descriptors by 1. The range lock is successfully acquired, and subsequent operations are protected by this lock.
[0138] ⑤ Perform insertion operations in the hierarchical VMA tree: Based on the target address range of each thread, the page table level to be stored is determined as the PT level by judging from the bottom up. The page table descriptors corresponding to each address range have been created in step ③ and can be used directly.
[0139] Each thread creates its own VMA segment: It allocates a VMA segment structure `vma_segment` from the SLAB cache and fills the embedded standard VMA structure `vm_area_struct` with standard VMA information (start address, end address, permissions, mapping type, etc.). It then sets the pointer of its page table descriptor to the page table descriptor from step ③, with the storage level set to PT level.
[0140] Each thread inserts the VMA fragment into the VMA subtree of the corresponding page table descriptor, adds it to the VMA fragment linked list vma_list of the page table descriptor, and updates the VMA fragment count vma_count of the PTD.
[0141] Since only one VMA segment is inserted in the VMA subtree of each page table descriptor and there are no adjacent VMAs, the merging step is skipped.
[0142] ⑥ Update VMA fragment cache: Each thread will populate the created VMA fragments into the current CPU's L1 cache and the process's L2 cache.
[0143] ⑦ Release the range lock: Each thread iterates through the locked list of the range lock object (containing only one page table descriptor) and calls `spin_unlock` to release its spinlock. Since `mmap` only reserves address space and does not establish a page table mapping, the delayed TLB refresh flag is not set, so there is no need to refresh the TLB.
[0144] ⑧ Return the mapped address: The kernel returns the virtual addresses allocated to each thread to the user program, and the entire mmap operation is complete.
[0145] In the above scenario, the four threads execute in complete parallelism without any lock contention. In contrast, in the traditional Linux kernel, due to the protection of the global mmap_lock, the four threads must execute serially, resulting in a total execution time approximately four times that of this embodiment. This embodiment reduces the lock granularity to a single 2MB address partition, allowing non-overlapping regions to run in complete parallelism, significantly improving multi-core scalability.
[0146] Compared with existing technologies, this embodiment provides a memory management method based on hierarchical VMA, which replaces the global mmap lock in the traditional Linux kernel with range locks. This achieves finer lock granularity from the entire address space to a single address partition, eliminating global lock contention and allowing operations in non-overlapping address regions to be executed concurrently, significantly improving memory usage performance in multi-core scenarios. The cache line contention problem of traditional global read / write semaphores is decomposed into fine-grained spin locks for each address partition. Locks for different address partitions are located in different memory locations, preventing multiple cores from modifying the same cache line simultaneously. Furthermore, the range lock employs a spin lock attempt-to-acquire strategy with extremely short lock holding times (microseconds). Upon failure, it immediately retryes instead of idling, avoiding prolonged spinning and deadlocks, thereby significantly reducing cache consistency traffic and lock access latency. A hierarchical VMA tree was constructed, storing VMA fragments hierarchically in page table descriptors at different page table levels according to their address range. During lookups, the system starts from the lowest page table level and ascends level by level. Leveraging the objective distribution characteristic that over 90% of VMAs are no larger than 2MB, the average lookup level is only 1.12 levels, significantly improving VMA lookup efficiency and reducing lookup latency. Through the synergistic effect of the hierarchical VMA tree and multi-level VMA fragment caching, the VMA lookup speed is effectively improved, and the efficiency of page fault handling is accelerated.
[0147] Those skilled in the art will understand that all or part of the processes of the methods described in the above embodiments can be implemented by a computer program instructing related hardware, and the program can be stored in a computer-readable storage medium. The computer-readable storage medium may be a disk, optical disk, read-only memory, or random access memory, etc.
[0148] The above description is only a preferred embodiment of the present invention, but the scope of protection of the present invention is not limited thereto. Any changes or substitutions that can be easily conceived by those skilled in the art within the scope of the technology disclosed in the present invention should be included within the scope of protection of the present invention.
Claims
1. A memory management method based on hierarchical VMA, characterized in that, Includes the following steps: When a request to operate on the virtual address space is received, the target address range involved in the operation request is obtained; Query the VMA fragment cache based on the target address range; If the VMA fragment cache does not hit the target VMA, a range lock is acquired corresponding to at least one address partition that intersects with the target address range; under the protection of the range lock, a VMA operation is performed in the hierarchical VMA tree according to the target address range; otherwise, a VMA operation is performed according to the hit target VMA. The VMA fragment cache is updated based on the result of the VMA operation.
2. The memory management method based on hierarchical VMA according to claim 1, characterized in that, The VMA segment cache includes: an L1 cache for each CPU core and an L2 cache for each process; the L1 cache stores the most recently accessed VMA entries of the current CPU core and the process identifiers to which each entry belongs; the L2 cache is managed using an adaptive replacement caching algorithm and is used to store process-level VMA entries.
3. The memory management method based on hierarchical VMA according to claim 1, characterized in that, The address partitions are defined by page table descriptors, and each page table descriptor corresponds to a non-overlapping address partition and belongs to a page table level; All page table descriptors at different page table levels are organized in the same radix tree according to the address range they cover and the page table level they belong to. The key of the radix tree is obtained by adding the offset of the page table level to which the page table descriptor belongs to the partition index. The partition index is obtained by right-shifting the virtual address within the address partition corresponding to the page table descriptor by the number of bits corresponding to the page table level to which the page table descriptor belongs.
4. The memory management method based on hierarchical VMA according to claim 3, characterized in that, The step of acquiring the range lock corresponding to at least one address partition intersecting with the target address range includes: The target page table level is determined based on the preset range granularity, and the corresponding address partition size is obtained as the step size. Using the starting virtual address of the target address range as the current address, the following search steps are repeated: Calculate the target key based on the current address and the target page table level; search for the page table descriptor corresponding to the target key in the radix tree; if it does not exist, create a new page table descriptor and insert it into the radix tree; increment the current address by one step to become the next current address and continue searching; until the current address is greater than or equal to the ending virtual address of the target address range, one or more page table descriptors intersecting with the address range are obtained; Acquire the corresponding spinlocks for one or more page table descriptors in sequence to form a range lock.
5. The memory management method based on hierarchical VMA according to claim 4, characterized in that, The step of sequentially acquiring corresponding spinlocks for one or more page table descriptors to form a range lock includes: Allocate a range lock object from the pre-allocated SLAB cache; for each obtained page table descriptor, call the spin lock acquisition attempt operation for that page table descriptor; if the acquisition attempt is successful, store the pointer of the page table descriptor in the locked list of the range lock object; if the spin lock acquisition attempt for any page table descriptor fails, traverse the locked list to release all acquired spin locks, return the range lock object to the SLAB cache, and return a failure status to trigger a retry of the operation request; if the spin lock acquisition attempts for all page table descriptors are successful, the range lock acquisition is successful.
6. The memory management method based on hierarchical VMA according to claim 5, characterized in that, The range lock object includes: a pointer to the memory descriptor of the current process, the starting address of the range lock, the ending address of the range lock, a locked list, the number of locked page table descriptors, an operation type flag, a delayed TLB refresh flag, and the starting and ending addresses of the delayed TLB refresh.
7. The memory management method based on hierarchical VMA according to claim 3, characterized in that, The hierarchical VMA tree is constructed in the following way: A red-black tree is allocated as a VMA subtree for each page table descriptor. The VMA subtree is used to store VMA segments belonging to the address partition corresponding to the page table descriptor. Page table descriptors of different page table levels are organized into a hierarchical structure according to the address range they cover. Each VMA segment embeds a standard VMA structure as its first member and contains a pointer to its page table descriptor and the node structure of the VMA segment in the VMA subtree.
8. The memory management method based on hierarchical VMA according to claim 7, characterized in that, The step of performing VMA operations in the hierarchical VMA tree based on the target address range includes: When the VMA operation is a lookup operation, the starting virtual address of the target address range is used as the lookup target. Following the order from the bottom page table level to the top page table level, the following lookup operations are performed sequentially in the page table descriptors corresponding to each page table level: obtain the lookup key according to the query target and the current page table level, and search for the corresponding page table descriptor in the radix tree; if not found, proceed to the next page table level; if found, search for the VMA segment containing the lookup target in the VMA subtree of that page table descriptor, until it is found or all page table levels have been traversed.
9. The memory management method based on hierarchical VMA according to claim 2, characterized in that, Updating the VMA fragment cache based on the result of the VMA operation includes: If the result of the VMA operation is that a target VMA is found, then the target VMA is inserted into the L1 cache of the current CPU core and the L2 cache of the current process; when inserting into the L1 cache, the LFU cache eviction policy is used.
10. The memory management method based on hierarchical VMA according to claim 2, characterized in that, The step of querying the VMA fragment cache based on the target address range includes: The target virtual address is the starting virtual address within the target address range. Access the L1 cache using the current CPU core number as the index, traverse the VMA entries in the L1 cache. If the process ID of the current process is inconsistent with the process ID in the VMA entry in the L1 cache, skip the VMA entry; otherwise, determine whether the target virtual address is within the address range of the VMA entry. If so, a hit is found, increment the access count of the VMA entry, and return the corresponding VMA pointer as the target VMA. If the L1 cache misses, the L2 cache is queried. If the L2 cache hits, the VMA pointer corresponding to the hit VMA entry is returned as the target VMA; otherwise, the result of the miss is returned.