summaryrefslogtreecommitdiff
path: root/network/netadaptercx/netvadapterlibrary/code/memory.cpp
blob: b7536531435406232e9c37d1a4f73e4019440ff9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright (C) Microsoft Corporation. All rights reserved.
#include "pch.hpp"
#include "memory.h"
#include <netadaptercx.h>
#include "trace.h"
#include "memory.tmh"

#if ((NETADAPTER_VERSION_MAJOR == 2) && (NETADAPTER_VERSION_MINOR >= 6))

NTSTATUS
Memory::Initialize(
    NETMEMORYCOLLECTION MemoryCollection,
    size_t BufferSize
)
{
    m_memoryCollection = MemoryCollection;
    
    for (size_t i = 0; i < PREALLOCATED_BUFFERS_COUNT; i++)
    {
        NET_MEMORY_CONFIG memoryConfig{};
        NET_MEMORY_CONFIG_INIT(
            &memoryConfig,
            m_buffers[i].VirtualAddress,
            BufferSize);

        RETURN_IF_NOT_STATUS_SUCCESS(
            NetMemoryCreate(
                MemoryCollection,
                &memoryConfig,
                &m_buffers[i].MemoryId
            ));
         
        m_buffersReadyToUse[i] = &m_buffers[i];
    }

    m_lastBufferToUse = PREALLOCATED_BUFFERS_COUNT;
    // Create WDF spinlock for the queue, parent to the queue's WDF handle
    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        status = WdfSpinLockCreate(&attributes, &m_spinLock);
        NT_ASSERT(NT_SUCCESS(status));
    }
    return STATUS_SUCCESS;
}

void
Memory::ReleaseAllMappings(
    void
)
{
    for (size_t i = 0; i < PREALLOCATED_BUFFERS_COUNT; i++)
    {
        NetMemoryDestroy(m_memoryCollection, m_buffers[i].MemoryId);
    }

    m_lastBufferToUse = 0;
    RtlZeroMemory(m_buffersReadyToUse, sizeof(m_buffersReadyToUse));
}

MemoryBuffer*
Memory::PopAvailableBuffer(
    void
)
{
    WdfSpinLockAcquire(m_spinLock);

    if (m_lastBufferToUse == 0)
    {
        WdfSpinLockRelease(m_spinLock);
        return nullptr;
    }
    auto returnbuffer = m_buffersReadyToUse[--m_lastBufferToUse];
    WdfSpinLockRelease(m_spinLock);

    return returnbuffer;
}

void
Memory::ReturnBuffer(
    MemoryBuffer* Buffer
)
{
    WdfSpinLockAcquire(m_spinLock);

    NT_FRE_ASSERT(m_lastBufferToUse < PREALLOCATED_BUFFERS_COUNT);

    m_buffersReadyToUse[m_lastBufferToUse++] = Buffer;
    WdfSpinLockRelease(m_spinLock);
}
#endif //NETCX 2.6 only

// for wil::make_unique_nothrow
void*
operator new(size_t s, std::nothrow_t const&)
{
    return operator new(s);
}