StephanvanSchaik / mmap-rs

A cross-platform and safe Rust API to create and manage memory mappings in the virtual address space of the calling process.
Apache License 2.0
59 stars 17 forks source link

windows: handle reserved memory correctly #26

Closed StephanvanSchaik closed 1 year ago

StephanvanSchaik commented 1 year ago

According to the documentation for VirtualFreeEx a reserved range of pages must be released entirely and pages cannot be released individually. This affects the splitting API introduced by PR #18, as the reservation must be kept alive as long as there are Mmap objects referring to that reserved area.

Internally, Microsoft Windows tracks areas in the virtual address space by using an AVL-tree of VADs (Virtual Address Descriptors). This likely means that reserving and releasing pages in the VirtualAlloc API is equivalent to allocating and freeing VADs directly. Since there does not seem to be a way to (transparently) merge or split VADs like on other operating systems, this means we can only release the entire VAD after the last Mmap object has been dropped.

This PR changes the Drop implementation of Mmap on Microsoft Windows to only decommit the pages, but not release them. When mapping memory, an Arc<ReservedArea> is created to keep track of the reserved area. More specifically, the Drop implementation of ReservedArea releases the VAD.

In addition, since UnmapViewOfFile only refers to the base address of the mapping, Mmap::split_off() and Mmap::split_to() cannot be used on such mappings on Microsoft Windows.

Furthermore, since there is no distinction between reserved and committed pages for a file mapping, Mmap keeps track of an Option<Arc<ReservedArea>>, such that it can be None for file mappings.

Finally, this PR adds another test case for the query API that kept failing on Microsoft Windows due to this issue.