win-numa-sys 0.1.1

Memory-safe Rust over the Windows NUMA APIs: a VirtualAllocExNuma-backed buffer, a NumaNode newtype, and the node queries a caller needs to decide what to pass. Thin over Win32, with no policy about which node anything should use.
Documentation
# win-numa-sys

Memory-safe Rust over the Windows NUMA APIs.

Windows provides some NUMA concepts; this crate builds library notions on top of them. Whether a
client uses them is up to the client.

## What is here

- **`NumaNode`** -- a node number, as Windows numbers them. A newtype because a node *number* and a
  *count* of nodes are both small integers and are trivially swapped at a call site.
- **`NumaBuffer`** -- an owned allocation made with `VirtualAllocExNuma` and released with
  `VirtualFree`, so a buffer can be placed on a chosen node rather than wherever the default
  allocator lands it.
- **`highest_numa_node()`** and **`volume_numa_node(handle)`** -- the two questions Windows will
  answer about nodes, wrapped so a caller can find a node to pass without writing the FFI.

## What is not here, and will not be

**Any opinion about which node anything should use.** This crate reports what Windows says and
allocates where it is told. It does not map a file to a node, does not shard anything, and does not
choose a node on a caller's behalf.

The `-sys` suffix is that promise. In this workspace the suffix means thin over Win32, memory-safe,
adding no policy -- see the repository's
[DESIGN-NOTES.md](../../DESIGN-NOTES.md#the-waitable-queues-crate-is-named-plural-and-carries-no-sys-suffix),
where a sibling crate drops the suffix for failing exactly that test.

## The name

The first crate here to take `win-` rather than `windows-`. `windows` is Microsoft's namespace, and
a crate published as `windows-numa-sys` today is a name they may reasonably want tomorrow; see
[DESIGN-NOTES.md](../../DESIGN-NOTES.md#new-crates-take-the-win-prefix). Existing crates keep their
names for now.

## A node argument is a preference, not an instruction

`VirtualAllocExNuma`'s parameter is `nndPreferred`, and the name is the contract. A successful
allocation is **not** evidence that the pages landed on the node that was asked for. Two things
follow, both of which have already caught someone in this workspace:

- Committed pages are demand-zero, so until something writes to them no physical page has been drawn
  from the preferred node at all. Measuring placement means faulting the pages in first.
- An *invalid* node is refused -- but `u32::MAX` is not a test of that, because it is the API's own
  no-preference sentinel and is accepted by design. A measurement that asks for `u32::MAX` and sees
  it succeed has measured the sentinel, not a range check.

Observing where pages actually landed needs `QueryWorkingSetEx`, which lives in
`windows-placement-probe` today; whether it moves here is [CHECKLIST.md](CHECKLIST.md) `N-1.2`.

## Buffer traits

`NumaBuffer` implements `io-buffers`' `IoBuf` and `IoBufMut`, so a ring takes it as a buffer as it
is. This crate defines no buffer trait of its own: the traits belong to `io-buffers`, which is
portable and so cannot depend on a Windows allocator, and the orphan rule lets only the crate that
owns the trait or the type implement it, which is why the implementations are here.

A crate that owns a buffer trait of its own implements it for `NumaBuffer` the same way, over the
inherent `as_ptr`, `as_mut_ptr` and `len`. See [DESIGN-NOTES.md](DESIGN-NOTES.md) `N-D-2`.