internal void ReturnNative(SharedMemory sm)
        {
            sm.FromOwnedDisposedToReleasingDisposed();

            Debug.Assert(sm.IsDisposed);
            ThrowHelper.AssertFailFast(sm.Header.FlagsCounter == (HeaderFlags.Releasing | HeaderFlags.IsDisposed), "ReturnNative: sm.Header.FlagsCounter == (HeaderFlags.Releasing | HeaderFlags.IsDisposed)");

            // Now the buffer is logically free. To be able to reuse it
            // we must return it to the free list. If the next operation fails
            // the buffer leaks. Since it is in shared memory it will be paged
            // and its backing RAM will be reused. Fails should happen very
            // rarely so leaving a small region of a file is not a big deal.
            // However we still have a logic to detect such cases.
            // Use RetryReturnNative(BufferRef) to try to return

            _bra.Free(sm.BufferRef);

            // Keep Releasing flag, it is ignored by Rent.
            // Do not clear instanceId, BRA.Allocate always overwrites it.
            // It is only needed when a buffer is in allocated list, the
            // value is irrelevant for free buffers.

            SharedMemory.Free(sm);
        }