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