1 /*
2 * Copyright (c) 2018-2021, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file cm_tracker.cpp
24 //! \brief Contains Class CmTracker definitions
25 //!
26
27 #include "cm_tracker.h"
28 #include "cm_debug.h"
29 #include "cm_common.h"
30 #include "cm_event_ex.h"
31
CmTracker(MOS_INTERFACE * osInterface)32 CmTracker::CmTracker(MOS_INTERFACE *osInterface):
33 m_osInterface(osInterface),
34 m_data(nullptr),
35 m_maxTaskNum(0),
36 m_nextTaskID(0)
37 {
38 MOS_ZeroMemory(&m_resource, sizeof(m_resource));
39 }
40
Initialize(uint32_t taskNum)41 MOS_STATUS CmTracker::Initialize(uint32_t taskNum)
42 {
43 m_maxTaskNum = taskNum;
44 uint32_t size = GetFrameTrackerOffset(0) + (m_maxTaskNum+1) * sizeof(_CmFrameTracker);
45 MOS_ALLOC_GFXRES_PARAMS allocParams;
46 MOS_ZeroMemory(&allocParams, sizeof(allocParams));
47 allocParams.Type = MOS_GFXRES_BUFFER;
48 allocParams.TileType = MOS_TILE_LINEAR;
49 allocParams.Format = Format_Buffer;
50 allocParams.dwBytes = size;
51 allocParams.pBufName = "CmTracker";
52
53 CM_CHK_MOSSTATUS_RETURN(m_osInterface->pfnAllocateResource(m_osInterface, &allocParams,
54 &m_resource));
55 CM_CHK_MOSSTATUS_RETURN(m_osInterface->pfnRegisterResource(m_osInterface, &m_resource,
56 true, true));
57 CM_CHK_MOSSTATUS_RETURN(m_osInterface->pfnSkipResourceSync(&m_resource));
58
59 MOS_LOCK_PARAMS lockParams;
60 MOS_ZeroMemory(&lockParams, sizeof(lockParams));
61 lockParams.ReadOnly = 1;
62 lockParams.ForceCached = true;
63 m_data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, &m_resource, &lockParams);
64
65 MOS_ZeroMemory(m_data, size);
66
67 // init the tracker producer
68 m_trackerProducer.Initialize(m_osInterface);
69
70 return MOS_STATUS_SUCCESS;
71 }
72
~CmTracker()73 CmTracker::~CmTracker()
74 {
75 MOS_GFXRES_FREE_FLAGS resFreeFlags = {0};
76
77 resFreeFlags.AssumeNotInUse = 1;
78
79 m_osInterface->pfnFreeResourceWithFlag(m_osInterface, &m_resource, resFreeFlags.Value);
80 }
81
AssignFrameTracker(uint32_t trackerIndex,uint32_t * taskId,uint32_t * tracker,bool hasEvent)82 MOS_STATUS CmTracker::AssignFrameTracker(uint32_t trackerIndex, uint32_t *taskId, uint32_t *tracker, bool hasEvent)
83 {
84 int id = -1;
85 for (uint32_t i = 0; i < m_maxTaskNum; i++)
86 {
87 id = (int)m_nextTaskID + i;
88 id = id%m_maxTaskNum;
89 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(id));
90 if (frameTracker->valid == 0)
91 {
92 frameTracker->valid = hasEvent?1:0;
93 frameTracker->tracker = m_trackerProducer.GetNextTracker(trackerIndex);
94 frameTracker->trackerIndex = trackerIndex;
95 frameTracker->start = CM_INVALID_INDEX;
96 frameTracker->end = CM_INVALID_INDEX;
97 *taskId = id;
98 *tracker = frameTracker->tracker;
99 m_trackerProducer.StepForward(trackerIndex);
100 m_nextTaskID = *taskId + 1;
101 return MOS_STATUS_SUCCESS;
102 }
103 }
104
105 // can't find a slot for a new task
106 // just assign the tracker and dummy task
107 *taskId = m_maxTaskNum;
108 *tracker = m_trackerProducer.GetNextTracker(trackerIndex);
109 m_trackerProducer.StepForward(trackerIndex);
110 return MOS_STATUS_UNKNOWN;
111 }
112
Query(uint32_t taskId)113 CM_HAL_TASK_STATUS CmTracker::Query(uint32_t taskId)
114 {
115 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(taskId));
116 if ((int)(frameTracker->tracker - *GetLatestTrackerAddr(frameTracker->trackerIndex)) <= 0
117 && frameTracker->end != CM_INVALID_INDEX)
118 {
119 return CM_TASK_FINISHED;
120 }
121 else if (frameTracker->start != CM_INVALID_INDEX)
122 {
123 return CM_TASK_IN_PROGRESS;
124 }
125 else
126 {
127 return CM_TASK_QUEUED;
128 }
129 }
130
Refresh()131 MOS_STATUS CmTracker::Refresh()
132 {
133 CM_STATUS status;
134 if (m_associatedEvents.size() == 0)
135 {
136 return MOS_STATUS_SUCCESS;
137 }
138 CMRT_UMD::CLock Locker(m_eventListSection);
139 CmEventEx* event = *(m_associatedEvents.begin());
140 event->GetStatus(status);
141 if (status == CM_STATUS_FINISHED)
142 {
143 m_associatedEvents.pop_front();
144 }
145 return MOS_STATUS_SUCCESS;
146 }
147
148
InvalidFrameTracker(uint32_t taskId)149 void CmTracker::InvalidFrameTracker(uint32_t taskId)
150 {
151 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(taskId));
152 frameTracker->valid = 0;
153 }
154
WaitForAllTasksFinished()155 CM_RETURN_CODE CmTracker::WaitForAllTasksFinished()
156 {
157 uint32_t targetTaskId[MAX_TRACKER_NUMBER];
158 uint32_t targetTracker[MAX_TRACKER_NUMBER];
159
160 MOS_ZeroMemory(targetTaskId, sizeof(targetTaskId));
161 MOS_ZeroMemory(targetTracker, sizeof(targetTracker));
162
163 uint32_t inExecution = 0;
164 for (uint32_t id = 0; id < m_maxTaskNum; id++)
165 {
166 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(id));
167 if (Query(id) != CM_TASK_FINISHED)
168 {
169 ++ inExecution;
170 if ((int)(frameTracker->tracker - targetTracker[frameTracker->trackerIndex]) > 0)
171 {
172 //update
173 targetTracker[frameTracker->trackerIndex] = frameTracker->tracker;
174 targetTaskId[frameTracker->trackerIndex] = id;
175 }
176 }
177 }
178
179 if (inExecution == 0) // no task pending at all
180 {
181 return CM_SUCCESS;
182 }
183
184 //Used for timeout detection
185 uint64_t freq, start, timeout;
186 MosUtilities::MosQueryPerformanceFrequency(&freq);
187 MosUtilities::MosQueryPerformanceCounter(&start);
188 timeout = start + (CM_MAX_TIMEOUT * freq * inExecution);
189
190 // wait for the last task to be finished (largest tracker)
191 for (int i = 0; i < MAX_TRACKER_NUMBER; i++)
192 {
193 if (targetTracker[i] == 0)
194 {
195 continue;
196 }
197 while (Query(targetTaskId[i]) != CM_TASK_FINISHED)
198 {
199 uint64_t current;
200 MosUtilities::MosQueryPerformanceCounter((uint64_t*)¤t);
201 if( current > timeout )
202 {
203 return CM_EXCEED_MAX_TIMEOUT;
204 }
205
206 }
207 }
208 return CM_SUCCESS;
209 }
210
211