1 /*
2 * Copyright (C) 2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include "shared/source/memory_manager/allocations_list.h"
9
10 #include "shared/source/command_stream/command_stream_receiver.h"
11
12 namespace NEO {
13
14 struct ReusableAllocationRequirements {
15 const void *requiredPtr;
16 size_t requiredMinimalSize;
17 volatile uint32_t *csrTagAddress;
18 GraphicsAllocation::AllocationType allocationType;
19 uint32_t contextId;
20 uint32_t activeTileCount;
21 uint32_t tagOffset;
22 };
23
AllocationsList(AllocationUsage allocationUsage)24 AllocationsList::AllocationsList(AllocationUsage allocationUsage)
25 : allocationUsage(allocationUsage) {}
26
AllocationsList()27 AllocationsList::AllocationsList()
28 : allocationUsage(REUSABLE_ALLOCATION) {}
29
detachAllocation(size_t requiredMinimalSize,const void * requiredPtr,CommandStreamReceiver * commandStreamReceiver,GraphicsAllocation::AllocationType allocationType)30 std::unique_ptr<GraphicsAllocation> AllocationsList::detachAllocation(size_t requiredMinimalSize, const void *requiredPtr, CommandStreamReceiver *commandStreamReceiver, GraphicsAllocation::AllocationType allocationType) {
31 ReusableAllocationRequirements req;
32 req.requiredMinimalSize = requiredMinimalSize;
33 req.csrTagAddress = (commandStreamReceiver == nullptr) ? nullptr : commandStreamReceiver->getTagAddress();
34 req.allocationType = allocationType;
35 req.contextId = (commandStreamReceiver == nullptr) ? UINT32_MAX : commandStreamReceiver->getOsContext().getContextId();
36 req.requiredPtr = requiredPtr;
37 req.activeTileCount = (commandStreamReceiver == nullptr) ? 1u : commandStreamReceiver->getActivePartitions();
38 req.tagOffset = (commandStreamReceiver == nullptr) ? 0u : commandStreamReceiver->getPostSyncWriteOffset();
39 GraphicsAllocation *a = nullptr;
40 GraphicsAllocation *retAlloc = processLocked<AllocationsList, &AllocationsList::detachAllocationImpl>(a, static_cast<void *>(&req));
41 return std::unique_ptr<GraphicsAllocation>(retAlloc);
42 }
43
detachAllocationImpl(GraphicsAllocation *,void * data)44 GraphicsAllocation *AllocationsList::detachAllocationImpl(GraphicsAllocation *, void *data) {
45 ReusableAllocationRequirements *req = static_cast<ReusableAllocationRequirements *>(data);
46 auto *curr = head;
47 while (curr != nullptr) {
48 if ((req->allocationType == curr->getAllocationType()) &&
49 (curr->getUnderlyingBufferSize() >= req->requiredMinimalSize)) {
50 if (req->csrTagAddress == nullptr) {
51 return removeOneImpl(curr, nullptr);
52 }
53 if ((this->allocationUsage == TEMPORARY_ALLOCATION || checkTagAddressReady(req, curr)) &&
54 (req->requiredPtr == nullptr || req->requiredPtr == curr->getUnderlyingBuffer())) {
55 if (this->allocationUsage == TEMPORARY_ALLOCATION) {
56 // We may not have proper task count yet, so set notReady to avoid releasing in a different thread
57 curr->updateTaskCount(CompletionStamp::notReady, req->contextId);
58 }
59 return removeOneImpl(curr, nullptr);
60 }
61 }
62 curr = curr->next;
63 }
64 return nullptr;
65 }
66
freeAllGraphicsAllocations(Device * neoDevice)67 void AllocationsList::freeAllGraphicsAllocations(Device *neoDevice) {
68 auto *curr = head;
69 while (curr != nullptr) {
70 auto currNext = curr->next;
71 neoDevice->getMemoryManager()->freeGraphicsMemory(curr);
72 curr = currNext;
73 }
74 head = nullptr;
75 }
76
checkTagAddressReady(ReusableAllocationRequirements * requirements,GraphicsAllocation * gfxAllocation)77 bool AllocationsList::checkTagAddressReady(ReusableAllocationRequirements *requirements, GraphicsAllocation *gfxAllocation) {
78 auto tagAddress = requirements->csrTagAddress;
79 auto taskCount = gfxAllocation->getTaskCount(requirements->contextId);
80 for (uint32_t count = 0; count < requirements->activeTileCount; count++) {
81 if (*tagAddress < taskCount) {
82 return false;
83 }
84 tagAddress = ptrOffset(tagAddress, requirements->tagOffset);
85 }
86
87 return true;
88 }
89
90 } // namespace NEO
91