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*)&current);
197             if( current > timeout )
198             {
199                 return CM_EXCEED_MAX_TIMEOUT;
200             }
201 
202         }
203     }
204     return CM_SUCCESS;
205 }
206 
207