blob: 42e32009e4efa6ab258eb764b783673cd8c971e9 [file] [log] [blame]
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "BufferManager.hpp"
7#include "PacketBuffer.hpp"
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +01008
Cathal Corbett5aa9fd72022-02-25 15:33:28 +00009namespace arm
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010010{
11
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000012namespace pipe
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010013{
14
15BufferManager::BufferManager(unsigned int numberOfBuffers, unsigned int maxPacketSize)
Finn Williams09ad6f92019-12-19 17:05:18 +000016 : m_MaxBufferSize(maxPacketSize),
Jim Flynn0204f092020-06-22 20:41:43 +010017 m_NumberOfBuffers(numberOfBuffers),
18 m_MaxNumberOfBuffers(numberOfBuffers * 3),
19 m_CurrentNumberOfBuffers(numberOfBuffers)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010020{
Finn Williams09ad6f92019-12-19 17:05:18 +000021 Initialize();
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010022}
23
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000024IPacketBufferPtr BufferManager::Reserve(unsigned int requestedSize, unsigned int& reservedSize)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010025{
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010026 reservedSize = 0;
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010027 std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
28 if (requestedSize > m_MaxBufferSize)
29 {
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010030 return nullptr;
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010031 }
32 availableListLock.lock();
33 if (m_AvailableList.empty())
34 {
Jim Flynn0204f092020-06-22 20:41:43 +010035 if (m_CurrentNumberOfBuffers < m_MaxNumberOfBuffers)
36 {
37 // create a temporary overflow/surge buffer and hand it back
38 m_CurrentNumberOfBuffers++;
39 availableListLock.unlock();
40 IPacketBufferPtr buffer = std::make_unique<PacketBuffer>(m_MaxBufferSize);
41 reservedSize = requestedSize;
42 return buffer;
43 }
44 else
45 {
46 // we have totally busted the limit. call a halt to new memory allocations.
47 availableListLock.unlock();
48 return nullptr;
49 }
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010050 }
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000051 IPacketBufferPtr buffer = std::move(m_AvailableList.back());
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010052 m_AvailableList.pop_back();
53 availableListLock.unlock();
54 reservedSize = requestedSize;
55 return buffer;
56}
57
Sadik Armagan3896b472020-02-10 12:24:15 +000058void BufferManager::Commit(IPacketBufferPtr& packetBuffer, unsigned int size, bool notifyConsumer)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010059{
60 std::unique_lock<std::mutex> readableListLock(m_ReadableMutex, std::defer_lock);
61 packetBuffer->Commit(size);
62 readableListLock.lock();
Finn Williamsb6a402f2020-03-24 13:46:22 +000063 m_ReadableList.push(std::move(packetBuffer));
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010064 readableListLock.unlock();
Sadik Armagan3896b472020-02-10 12:24:15 +000065
66 if (notifyConsumer)
67 {
68 FlushReadList();
69 }
Finn Williams09ad6f92019-12-19 17:05:18 +000070}
71
72void BufferManager::Initialize()
73{
74 m_AvailableList.reserve(m_NumberOfBuffers);
Jim Flynn0204f092020-06-22 20:41:43 +010075 m_CurrentNumberOfBuffers = m_NumberOfBuffers;
Finn Williams09ad6f92019-12-19 17:05:18 +000076 for (unsigned int i = 0; i < m_NumberOfBuffers; ++i)
77 {
78 IPacketBufferPtr buffer = std::make_unique<PacketBuffer>(m_MaxBufferSize);
79 m_AvailableList.emplace_back(std::move(buffer));
80 }
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010081}
82
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000083void BufferManager::Release(IPacketBufferPtr& packetBuffer)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +010084{
85 std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
86 packetBuffer->Release();
87 availableListLock.lock();
Jim Flynn0204f092020-06-22 20:41:43 +010088 if (m_AvailableList.size() <= m_NumberOfBuffers)
89 {
90 m_AvailableList.push_back(std::move(packetBuffer));
91 }
92 else
93 {
94 // we have been handed a temporary overflow/surge buffer get rid of it
95 packetBuffer->Destroy();
96 if (m_CurrentNumberOfBuffers > m_NumberOfBuffers)
97 {
98 --m_CurrentNumberOfBuffers;
99 }
100 }
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100101 availableListLock.unlock();
102}
103
Finn Williams09ad6f92019-12-19 17:05:18 +0000104void BufferManager::Reset()
105{
106 //This method should only be called once all threads have been joined
107 std::lock_guard<std::mutex> readableListLock(m_ReadableMutex);
108 std::lock_guard<std::mutex> availableListLock(m_AvailableMutex);
109
110 m_AvailableList.clear();
Finn Williamsb6a402f2020-03-24 13:46:22 +0000111 std::queue<IPacketBufferPtr>().swap(m_ReadableList);
Finn Williams09ad6f92019-12-19 17:05:18 +0000112
113 Initialize();
114}
115
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000116IPacketBufferPtr BufferManager::GetReadableBuffer()
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100117{
118 std::unique_lock<std::mutex> readableListLock(m_ReadableMutex);
119 if (!m_ReadableList.empty())
120 {
Finn Williamsb6a402f2020-03-24 13:46:22 +0000121 IPacketBufferPtr buffer = std::move(m_ReadableList.front());
122 m_ReadableList.pop();
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100123 readableListLock.unlock();
124 return buffer;
125 }
126 return nullptr;
127}
128
Matteo Martincigh2ffcc412019-11-05 11:47:40 +0000129void BufferManager::MarkRead(IPacketBufferPtr& packetBuffer)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100130{
131 std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
132 packetBuffer->MarkRead();
133 availableListLock.lock();
Jim Flynn0204f092020-06-22 20:41:43 +0100134 if (m_AvailableList.size() <= m_NumberOfBuffers)
135 {
136 m_AvailableList.push_back(std::move(packetBuffer));
137 }
138 else
139 {
140 // we have been handed a temporary overflow/surge buffer get rid of it
141 packetBuffer->Destroy();
142 if (m_CurrentNumberOfBuffers > m_NumberOfBuffers)
143 {
144 --m_CurrentNumberOfBuffers;
145 }
146 }
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100147 availableListLock.unlock();
148}
149
Sadik Armagan3896b472020-02-10 12:24:15 +0000150void BufferManager::SetConsumer(IConsumer* consumer)
151{
152 m_Consumer = consumer;
153}
154
155void BufferManager::FlushReadList()
156{
157 // notify consumer that packet is ready to read
158 if (m_Consumer != nullptr)
159 {
160 m_Consumer->SetReadyToRead();
161 }
162}
163
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000164} // namespace pipe
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100165
Cathal Corbett5aa9fd72022-02-25 15:33:28 +0000166} // namespace arm