1 /*
2 * Copyright (c) 2018-2019, 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 m_osInterface->pfnFreeResourceWithFlag(m_osInterface, &m_resource, 1);
76 }
77
AssignFrameTracker(uint32_t trackerIndex,uint32_t * taskId,uint32_t * tracker,bool hasEvent)78 MOS_STATUS CmTracker::AssignFrameTracker(uint32_t trackerIndex, uint32_t *taskId, uint32_t *tracker, bool hasEvent)
79 {
80 int id = -1;
81 for (uint32_t i = 0; i < m_maxTaskNum; i++)
82 {
83 id = (int)m_nextTaskID + i;
84 id = id%m_maxTaskNum;
85 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(id));
86 if (frameTracker->valid == 0)
87 {
88 frameTracker->valid = hasEvent?1:0;
89 frameTracker->tracker = m_trackerProducer.GetNextTracker(trackerIndex);
90 frameTracker->trackerIndex = trackerIndex;
91 frameTracker->start = CM_INVALID_INDEX;
92 frameTracker->end = CM_INVALID_INDEX;
93 *taskId = id;
94 *tracker = frameTracker->tracker;
95 m_trackerProducer.StepForward(trackerIndex);
96 m_nextTaskID = *taskId + 1;
97 return MOS_STATUS_SUCCESS;
98 }
99 }
100
101 // can't find a slot for a new task
102 // just assign the tracker and dummy task
103 *taskId = m_maxTaskNum;
104 *tracker = m_trackerProducer.GetNextTracker(trackerIndex);
105 m_trackerProducer.StepForward(trackerIndex);
106 return MOS_STATUS_UNKNOWN;
107 }
108
Query(uint32_t taskId)109 CM_HAL_TASK_STATUS CmTracker::Query(uint32_t taskId)
110 {
111 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(taskId));
112 if ((int)(frameTracker->tracker - *GetLatestTrackerAddr(frameTracker->trackerIndex)) <= 0
113 && frameTracker->end != CM_INVALID_INDEX)
114 {
115 return CM_TASK_FINISHED;
116 }
117 else if (frameTracker->start != CM_INVALID_INDEX)
118 {
119 return CM_TASK_IN_PROGRESS;
120 }
121 else
122 {
123 return CM_TASK_QUEUED;
124 }
125 }
126
Refresh()127 MOS_STATUS CmTracker::Refresh()
128 {
129 CM_STATUS status;
130 if (m_associatedEvents.size() == 0)
131 {
132 return MOS_STATUS_SUCCESS;
133 }
134 CMRT_UMD::CLock Locker(m_eventListSection);
135 CmEventEx* event = *(m_associatedEvents.begin());
136 event->GetStatus(status);
137 if (status == CM_STATUS_FINISHED)
138 {
139 m_associatedEvents.pop_front();
140 }
141 return MOS_STATUS_SUCCESS;
142 }
143
144
InvalidFrameTracker(uint32_t taskId)145 void CmTracker::InvalidFrameTracker(uint32_t taskId)
146 {
147 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(taskId));
148 frameTracker->valid = 0;
149 }
150
WaitForAllTasksFinished()151 CM_RETURN_CODE CmTracker::WaitForAllTasksFinished()
152 {
153 uint32_t targetTaskId[MAX_TRACKER_NUMBER];
154 uint32_t targetTracker[MAX_TRACKER_NUMBER];
155
156 MOS_ZeroMemory(targetTaskId, sizeof(targetTaskId));
157 MOS_ZeroMemory(targetTracker, sizeof(targetTracker));
158
159 uint32_t inExecution = 0;
160 for (uint32_t id = 0; id < m_maxTaskNum; id++)
161 {
162 _CmFrameTracker *frameTracker = (_CmFrameTracker *)(m_data + GetFrameTrackerOffset(id));
163 if (Query(id) != CM_TASK_FINISHED)
164 {
165 ++ inExecution;
166 if ((int)(frameTracker->tracker - targetTracker[frameTracker->trackerIndex]) > 0)
167 {
168 //update
169 targetTracker[frameTracker->trackerIndex] = frameTracker->tracker;
170 targetTaskId[frameTracker->trackerIndex] = id;
171 }
172 }
173 }
174
175 if (inExecution == 0) // no task pending at all
176 {
177 return CM_SUCCESS;
178 }
179
180 //Used for timeout detection
181 uint64_t freq, start, timeout;
182 MOS_QueryPerformanceFrequency(&freq);
183 MOS_QueryPerformanceCounter(&start);
184 timeout = start + (CM_MAX_TIMEOUT * freq * inExecution);
185
186 // wait for the last task to be finished (largest tracker)
187 for (int i = 0; i < MAX_TRACKER_NUMBER; i++)
188 {
189 if (targetTracker[i] == 0)
190 {
191 continue;
192 }
193 while (Query(targetTaskId[i]) != CM_TASK_FINISHED)
194 {
195 uint64_t current;
196 MOS_QueryPerformanceCounter((uint64_t*)¤t);
197 if( current > timeout )
198 {
199 return CM_EXCEED_MAX_TIMEOUT;
200 }
201
202 }
203 }
204 return CM_SUCCESS;
205 }
206
207