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*)&current);
201             if( current > timeout )
202             {
203                 return CM_EXCEED_MAX_TIMEOUT;
204             }
205 
206         }
207     }
208     return CM_SUCCESS;
209 }
210 
211