1 /*
2 * Copyright (c) 2007-2017, 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_event_rt.cpp
24 //! \brief     Contains OS-agnostic CmEventRT member functions.
25 //!
26 
27 #include "cm_event_rt.h"
28 
29 #include "cm_device_rt.h"
30 #include "cm_queue_rt.h"
31 #include "cm_mem.h"
32 #include "cm_task_rt.h"
33 #include "cm_kernel_rt.h"
34 #include "cm_thread_space_rt.h"
35 #include "cm_group_space.h"
36 #include "cm_surface_manager.h"
37 #include "cm_task_internal.h"
38 
39 namespace CMRT_UMD
40 {
41 //*-----------------------------------------------------------------------------
42 //| Purpose:    Create Cm Event
43 //| Returns:    Result of the operation.
44 //*-----------------------------------------------------------------------------
Create(uint32_t index,CmQueueRT * queue,CmTaskInternal * task,int32_t taskDriverId,CmDeviceRT * device,bool isVisible,CmEventRT * & event)45 int32_t CmEventRT::Create(uint32_t index, CmQueueRT *queue, CmTaskInternal *task, int32_t taskDriverId, CmDeviceRT *device, bool isVisible, CmEventRT *&event)
46 {
47     int32_t result = CM_SUCCESS;
48     event = new (std::nothrow) CmEventRT( index, queue, task, taskDriverId, device, isVisible );
49     if( event )
50     {
51         if(isVisible)
52         {   // Increase the refcount when the Event is visiable
53             event->Acquire();
54         }
55         result = event->Initialize();
56         if( result != CM_SUCCESS )
57         {
58             CmEventRT::Destroy( event );
59         }
60     }
61     else
62     {
63         CM_ASSERTMESSAGE("Error: Failed to create CmEvent due to out of system memory.");
64         result = CM_OUT_OF_HOST_MEMORY;
65     }
66     return result;
67 }
68 
69 //*-----------------------------------------------------------------------------
70 //| Purpose:    Destroy Cm Event
71 //| Returns:    Result of the operation.
72 //*-----------------------------------------------------------------------------
Destroy(CmEventRT * & event)73 int32_t CmEventRT::Destroy( CmEventRT* &event )
74 {
75     long refCount = event->SafeRelease();
76     if( refCount == 0 )
77     {
78         event = nullptr;
79     }
80 
81     return CM_SUCCESS;
82 }
83 
84 //*-----------------------------------------------------------------------------
85 //| Purpose:    Constructor of Cm Event
86 //| Returns:    Result of the operation.
87 //*-----------------------------------------------------------------------------
CmEventRT(uint32_t index,CmQueueRT * queue,CmTaskInternal * task,int32_t taskDriverId,CmDeviceRT * device,bool isVisible)88 CmEventRT::CmEventRT(uint32_t index, CmQueueRT *queue, CmTaskInternal *task, int32_t taskDriverId, CmDeviceRT *device, bool isVisible):
89     m_index( index ),
90     m_taskDriverId( taskDriverId ),
91     m_osData(nullptr),
92     m_status( CM_STATUS_QUEUED ),
93     m_time( 0 ),
94     m_ticks(0),
95     m_hwStartTimeStampInTicks( 0 ),
96     m_hwEndTimeStampInTicks( 0 ),
97     m_device( device ),
98     m_queue (queue),
99     m_refCount(0),
100     m_isVisible(isVisible),
101     m_task(task),
102     m_callbackFunction(nullptr),
103     m_callbackUserData(nullptr),
104     m_osSignalTriggered(false)
105 {
106     m_globalSubmitTimeCpu.QuadPart = 0;
107     m_submitTimeGpu.QuadPart = 0;
108     m_hwStartTimeStamp.QuadPart = 0;
109     m_hwEndTimeStamp.QuadPart = 0;
110     m_completeTime.QuadPart = 0;
111     m_enqueueTime.QuadPart = 0;
112 
113     m_kernelNames          = nullptr ;
114     m_threadSpace          = nullptr ;
115     m_kernelCount          = 0 ;
116 
117     MOS_ZeroMemory(&m_surEntryInfoArrays, sizeof(m_surEntryInfoArrays));
118 }
119 
120 //*-----------------------------------------------------------------------------
121 //| Purpose:    Increase Reference count
122 //| Returns:    Result of the operation.
123 //*-----------------------------------------------------------------------------
Acquire(void)124 int32_t CmEventRT::Acquire( void )
125 {
126     ++m_refCount;
127     return m_refCount;
128 }
129 
130 //*-----------------------------------------------------------------------------
131 //| Purpose:    De of Cm Event
132 //| Returns:    Result of the operation.
133 //*-----------------------------------------------------------------------------
SafeRelease(void)134 int32_t CmEventRT::SafeRelease( void )
135 {
136     --m_refCount;
137     if(m_refCount == 0 )
138     {
139         delete this;
140         return 0;
141     }
142     else
143     {
144         return m_refCount;
145     }
146 }
147 
148 //*-----------------------------------------------------------------------------
149 //| Purpose:    Destructor of Cm Event
150 //| Returns:    Result of the operation.
151 //*-----------------------------------------------------------------------------
~CmEventRT(void)152 CmEventRT::~CmEventRT( void )
153 {
154     // call callback registered by Vtune
155     if(m_callbackFunction)
156     {
157         m_callbackFunction(this, m_callbackUserData);
158     }
159 
160     if (m_surEntryInfoArrays.surfEntryInfosArray!= nullptr)
161     {
162 
163         for( uint32_t i = 0; i < m_surEntryInfoArrays.kernelNum; i ++ )
164         {
165             MosSafeDelete(m_surEntryInfoArrays.surfEntryInfosArray[i].surfEntryInfos);
166             MosSafeDelete(m_surEntryInfoArrays.surfEntryInfosArray[i].globalSurfInfos);
167         }
168         MosSafeDelete(m_surEntryInfoArrays.surfEntryInfosArray);
169     }
170 
171     if (m_kernelNames != nullptr)
172     {
173         for ( uint32_t i = 0; i < m_kernelCount; i++)
174         {
175             MosSafeDeleteArray(m_kernelNames[i]);
176         }
177         MosSafeDeleteArray( m_kernelNames );
178         MosSafeDeleteArray( m_threadSpace );
179     }
180 }
181 
182 //*-----------------------------------------------------------------------------
183 //| Purpose:    Initialize Cm Event
184 //| Returns:    Result of the operation.
185 //*-----------------------------------------------------------------------------
Initialize(void)186 int32_t CmEventRT::Initialize(void)
187 {
188     if( m_taskDriverId == -1 )
189         // -1 is an invalid task id in driver, i.e. the task has NOT been passed down to driver yet
190         // event is created at the enqueue time, so initial value is CM_STATUS_QUEUED
191     {
192         m_status = CM_STATUS_QUEUED;
193     }
194     else
195     {
196         CM_ASSERTMESSAGE("Error: Failed to initialize CmEvent.");
197         return CM_FAILURE;
198     }
199 
200     m_kernelNames = nullptr;
201     m_kernelCount = 0;
202 
203     return CM_SUCCESS;
204 }
205 
GetStatusNoFlush(CM_STATUS & status)206 int32_t CmEventRT::GetStatusNoFlush(CM_STATUS& status)
207 {
208     if ((m_status == CM_STATUS_FLUSHED) || (m_status == CM_STATUS_STARTED))
209     {
210         Query();
211     }
212     else if (m_status == CM_STATUS_QUEUED)
213     {
214         // the task hasn't beeen flushed yet
215         // if the task correspoonding to this event can be flushed, m_status will change to CM_STATUS_FLUSHED
216         m_queue->FlushTaskWithoutSync();
217 
218     }
219     else if (m_status == CM_STATUS_FINISHED)
220     {
221         //Do nothing
222     }
223     else
224     {
225         CM_ASSERTMESSAGE("Error: Failed to get status.");
226     }
227 
228     status = m_status;
229     return CM_SUCCESS;
230 }
231 
ModifyStatus(CM_STATUS status,uint64_t elapsedTime)232 int32_t CmEventRT::ModifyStatus(CM_STATUS status, uint64_t elapsedTime)
233 {
234     if (m_ticks == 0)
235     {
236         m_time = elapsedTime;
237     }
238     m_status = status;
239     return CM_SUCCESS;
240 }
241 
GetQueue(CmQueueRT * & queue)242 int32_t CmEventRT::GetQueue(CmQueueRT *& queue)
243 {
244     queue = m_queue;
245     return CM_SUCCESS;
246 }
247 
248 //*-----------------------------------------------------------------------------
249 //! Query the execution time of a task( one kernel or multiples kernels running concurrently )
250 //! in the unit of nanoseconds.
251 //! The execution time is from the time when the task starts to execution in GPU to the time
252 //! when the task finished execution
253 //! This is a non-blocking call.
254 //! INPUT:
255 //!     Reference to time
256 //! OUTPUT:
257 //!     CM_SUCCESS if the execution time is successfully returned
258 //!     CM_FAILURE if not, e.g. the task hasn't finished
259 //*-----------------------------------------------------------------------------
GetExecutionTime(uint64_t & time)260 CM_RT_API int32_t CmEventRT::GetExecutionTime(uint64_t& time)
261 {
262     CM_STATUS eventStatus = CM_STATUS_QUEUED;
263 
264     GetStatusNoFlush(eventStatus);
265 
266     if( eventStatus == CM_STATUS_FINISHED )
267     {
268         time = m_time;
269         return CM_SUCCESS;
270     }
271     else
272     {
273         return CM_FAILURE;
274     }
275 }
276 
GetExecutionTickTime(uint64_t & ticks)277 CM_RT_API int32_t CmEventRT::GetExecutionTickTime(uint64_t& ticks)
278 {
279     CM_STATUS eventStatus = CM_STATUS_QUEUED;
280 
281     GetStatusNoFlush(eventStatus);
282 
283     if (eventStatus == CM_STATUS_FINISHED)
284     {
285         ticks = m_ticks;
286         return CM_SUCCESS;
287     }
288     else
289     {
290         return CM_FAILURE;
291     }
292 }
293 
GetSubmitTime(LARGE_INTEGER * time)294 int32_t CmEventRT::GetSubmitTime(LARGE_INTEGER* time)
295 {
296 
297     CM_STATUS eventStatus = CM_STATUS_QUEUED;
298 
299     GetStatusNoFlush(eventStatus);
300 
301     if( eventStatus == CM_STATUS_FINISHED )
302     {
303         *time = m_globalSubmitTimeCpu;
304         return CM_SUCCESS;
305     }
306     else
307     {
308         CM_ASSERTMESSAGE("Error: Failed to get task submit time.");
309         return CM_FAILURE;
310     }
311 }
312 
GetHWStartTime(LARGE_INTEGER * time)313 int32_t CmEventRT::GetHWStartTime(LARGE_INTEGER* time)
314 {
315     CM_STATUS eventStatus = CM_STATUS_QUEUED;
316 
317     GetStatusNoFlush(eventStatus);
318 
319     if( eventStatus == CM_STATUS_FINISHED )
320     {
321         time->QuadPart = m_globalSubmitTimeCpu.QuadPart + m_hwStartTimeStamp.QuadPart - m_submitTimeGpu.QuadPart;
322         return CM_SUCCESS;
323     }
324     else
325     {
326         return CM_FAILURE;
327     }
328 
329 }
330 
GetKernelCount()331 uint32_t CmEventRT::GetKernelCount()
332 {
333     return m_kernelCount;
334 }
335 
GetHWEndTime(LARGE_INTEGER * time)336 int32_t CmEventRT::GetHWEndTime(LARGE_INTEGER* time)
337 {
338 
339     CM_STATUS eventStatus = CM_STATUS_QUEUED;
340 
341     GetStatusNoFlush(eventStatus);
342 
343     if( eventStatus == CM_STATUS_FINISHED )
344     {
345         time->QuadPart = m_globalSubmitTimeCpu.QuadPart + m_hwEndTimeStamp.QuadPart - m_submitTimeGpu.QuadPart;
346         return CM_SUCCESS;
347     }
348     else
349     {
350         return CM_FAILURE;
351     }
352 }
353 
GetCompleteTime(LARGE_INTEGER * time)354 int32_t CmEventRT::GetCompleteTime(LARGE_INTEGER* time)
355 {
356 
357     CM_STATUS eventStatus = CM_STATUS_QUEUED;
358 
359     GetStatusNoFlush(eventStatus);
360 
361     if( eventStatus == CM_STATUS_FINISHED )
362     {
363         *time = m_completeTime;
364         return CM_SUCCESS;
365     }
366     else
367     {
368         return CM_FAILURE;
369     }
370 
371 }
372 
GetEnqueueTime(LARGE_INTEGER * time)373 int32_t CmEventRT::GetEnqueueTime(LARGE_INTEGER* time)
374 {
375     CM_STATUS eventStatus = CM_STATUS_QUEUED;
376 
377     GetStatusNoFlush( eventStatus );
378 
379     if ( eventStatus == CM_STATUS_FINISHED )
380     {
381         *time = m_enqueueTime;
382         return CM_SUCCESS;
383     }
384     else
385     {
386         return CM_FAILURE;
387     }
388 
389 }
390 
SetKernelNames(CmTaskRT * task,CmThreadSpaceRT * threadSpace,CmThreadGroupSpace * threadGroupSpace)391 int32_t CmEventRT::SetKernelNames(CmTaskRT* task, CmThreadSpaceRT* threadSpace, CmThreadGroupSpace* threadGroupSpace)
392 {
393     uint32_t i = 0;
394     int32_t hr = CM_SUCCESS;
395     uint32_t threadCount;
396     m_kernelCount = task->GetKernelCount();
397 
398     // Alloc memory for kernel names
399     m_kernelNames = MOS_NewArray(char*, m_kernelCount);
400     m_threadSpace = MOS_NewArray(uint32_t, (4*m_kernelCount));
401     CM_CHK_NULL_GOTOFINISH(m_kernelNames, CM_OUT_OF_HOST_MEMORY);
402     CmSafeMemSet(m_kernelNames, 0, m_kernelCount*sizeof(char*) );
403     CM_CHK_NULL_GOTOFINISH(m_threadSpace, CM_OUT_OF_HOST_MEMORY);
404 
405     for (i = 0; i < m_kernelCount; i++)
406     {
407         m_kernelNames[i] = MOS_NewArray(char, CM_MAX_KERNEL_NAME_SIZE_IN_BYTE);
408         CM_CHK_NULL_GOTOFINISH(m_kernelNames[i], CM_OUT_OF_HOST_MEMORY);
409         CmKernelRT* kernel = task->GetKernelPointer(i);
410         MOS_SecureStrcpy(m_kernelNames[i], CM_MAX_KERNEL_NAME_SIZE_IN_BYTE, kernel->GetName());
411 
412         kernel->GetThreadCount(threadCount);
413         m_threadSpace[4 * i] = threadCount;
414         m_threadSpace[4 * i + 1] = 1;
415         m_threadSpace[4 * i + 2] = threadCount;
416         m_threadSpace[4 * i + 3] = 1;
417     }
418 
419     if (threadSpace)
420     {
421         uint32_t threadWidth, threadHeight;
422         threadSpace->GetThreadSpaceSize(threadWidth, threadHeight);
423         m_threadSpace[0] = threadWidth;
424         m_threadSpace[1] = threadHeight;
425         m_threadSpace[2] = threadWidth;
426         m_threadSpace[3] = threadHeight;
427     }
428     else if (threadGroupSpace)
429     {
430         uint32_t threadWidth, threadHeight, threadDepth, groupWidth, groupHeight, groupDepth;
431         threadGroupSpace->GetThreadGroupSpaceSize(threadWidth, threadHeight, threadDepth, groupWidth, groupHeight, groupDepth);
432         m_threadSpace[0] = threadWidth;
433         m_threadSpace[1] = threadHeight;
434         m_threadSpace[2] = threadWidth * groupWidth;
435         m_threadSpace[3] = threadHeight * groupHeight * groupDepth;
436     }
437 
438 finish:
439     if(hr == CM_OUT_OF_HOST_MEMORY)
440     {
441         if(m_kernelNames != nullptr)
442         {
443             for (uint32_t j = 0; j < m_kernelCount; j++)
444             {
445                 MosSafeDeleteArray(m_kernelNames[j]);
446             }
447         }
448         MosSafeDeleteArray(m_kernelNames);
449         MosSafeDeleteArray(m_threadSpace);
450     }
451     return hr;
452 }
453 
SetEnqueueTime(LARGE_INTEGER time)454 int32_t CmEventRT::SetEnqueueTime( LARGE_INTEGER time )
455 {
456     m_enqueueTime = time;
457     return CM_SUCCESS;
458 }
459 
SetCompleteTime(LARGE_INTEGER time)460 int32_t CmEventRT::SetCompleteTime( LARGE_INTEGER time )
461 {
462     m_completeTime = time;
463     return CM_SUCCESS;
464 }
465 
GetIndex(uint32_t & index)466 int32_t CmEventRT::GetIndex( uint32_t & index )
467 {
468     index = m_index;
469     return CM_SUCCESS;
470 }
471 
472 //*-----------------------------------------------------------------------------
473 //| Purpose:    Set Task ID
474 //| Returns:    Result of the operation.
475 //*-----------------------------------------------------------------------------
SetTaskDriverId(int32_t id)476 int32_t CmEventRT::SetTaskDriverId( int32_t id )
477 {
478     m_taskDriverId = id;
479     if( m_taskDriverId > -1 )
480         // Valid task id in driver, i.e. the task has been passed down to driver
481     {
482         m_status = CM_STATUS_FLUSHED;
483     }
484     else if( m_taskDriverId == -1 )
485         // -1 is an invalid task id in driver, i.e. the task has NOT been passed down to driver yet
486         // event is created at the enqueue time, so initial value is CM_STATUS_QUEUED
487     {
488         m_status = CM_STATUS_QUEUED;
489     }
490     else
491     {
492         CM_ASSERTMESSAGE("Error: Failed to set task driver ID.");
493         return CM_FAILURE;
494     }
495 
496     return CM_SUCCESS;
497 }
498 
499 //*-----------------------------------------------------------------------------
500 //| Purpose:    Set OS data
501 //| Returns:    Result of the operation.
502 //*-----------------------------------------------------------------------------
SetTaskOsData(void * data)503 int32_t CmEventRT::SetTaskOsData( void  *data )
504 {
505     m_osData = data;
506     return CM_SUCCESS;
507 }
508 
509 //*-----------------------------------------------------------------------------
510 //| Purpose:    Get Task ID
511 //| Returns:    Result of the operation.
512 //*-----------------------------------------------------------------------------
GetTaskDriverId(int32_t & id)513 int32_t CmEventRT::GetTaskDriverId( int32_t & id )
514 {
515     id = m_taskDriverId;
516     return CM_SUCCESS;
517 }
518 
519 //*-----------------------------------------------------------------------------
520 //| Purpose:    Query status of a task.
521 //| Returns:    Result of the operation.
522 //*-----------------------------------------------------------------------------
Query(void)523 int32_t CmEventRT::Query( void )
524 {
525     CM_RETURN_CODE  hr = CM_SUCCESS;
526 
527     CLock Lock(m_criticalSectionQuery);
528 
529     if( ( m_status != CM_STATUS_FLUSHED ) && ( m_status != CM_STATUS_STARTED ) )
530     {
531         return CM_FAILURE;
532     }
533 
534     CM_ASSERT( m_taskDriverId > -1 );
535     CM_HAL_QUERY_TASK_PARAM param;
536     CmSafeMemSet(&param, 0, sizeof(CM_HAL_QUERY_TASK_PARAM));
537     param.taskId = m_taskDriverId;
538     m_task->GetTaskType(param.taskType);
539     param.queueOption = m_queue->GetQueueOption();
540 
541     PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)m_device->GetAccelData();
542 
543     CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnQueryTask(cmData->cmHalState, &param));
544 
545     if( param.status == CM_TASK_FINISHED )
546     {
547         std::vector<CmQueueRT *> &queue = m_device->GetQueue();
548 
549         m_time = param.taskDurationNs;
550         m_ticks = param.taskDurationTicks;
551         m_hwStartTimeStampInTicks = param.taskHWStartTimeStampInTicks;
552         m_hwEndTimeStampInTicks = param.taskHWEndTimeStampInTicks;
553         m_status = CM_STATUS_FINISHED;
554 
555         //Update the state tracking array when a task is finished
556 
557         if (queue.size() == 0)
558         {
559             CM_ASSERTMESSAGE("Error: Invalid CmQueue.");
560             return CM_NULL_POINTER;
561         }
562 
563         UnreferenceIfNeeded(m_osData);
564 
565         CmNotifierGroup *notifiers = m_device->GetNotifiers();
566         if (notifiers != nullptr)
567         {
568             notifiers->NotifyTaskCompleted(m_task);
569         }
570 
571         m_globalSubmitTimeCpu = param.taskGlobalSubmitTimeCpu;
572         m_submitTimeGpu = param.taskSubmitTimeGpu;
573         m_hwStartTimeStamp = param.taskHWStartTimeStamp;
574         m_hwEndTimeStamp = param.taskHWEndTimeStamp;
575 
576         EVENT_LOG(this);
577     }
578     else if( param.status == CM_TASK_IN_PROGRESS )
579     {
580         m_status = CM_STATUS_STARTED;
581     }
582     else if (param.status == CM_TASK_RESET)
583     {
584         m_status = CM_STATUS_RESET;
585     }
586 
587 finish:
588     return hr;
589 }
590 
591 //*-----------------------------------------------------------------------------
592 //| Purpose:    Get m_status.
593 //| Returns:    return m_status.
594 //*-----------------------------------------------------------------------------
GetStatusWithoutFlush()595 CM_STATUS CmEventRT::GetStatusWithoutFlush()
596 {
597     return m_status;
598 }
599 
600 //*-----------------------------------------------------------------------------
601 //| Purpose:    GT-PIN : Get Surface Details
602 //| Returns:    result of operation
603 //*-----------------------------------------------------------------------------
GetSurfaceDetails(uint32_t kernIndex,uint32_t surfBTI,CM_SURFACE_DETAILS & outDetails)604 CM_RT_API  int32_t CmEventRT::GetSurfaceDetails(uint32_t kernIndex, uint32_t surfBTI,CM_SURFACE_DETAILS & outDetails )
605 {
606     CM_SURFACE_DETAILS *tempSurfInfo;
607     CmSurfaceManager *surfaceMgr;
608     m_device->GetSurfaceManager( surfaceMgr);
609 
610     if(!m_device->CheckGTPinEnabled())
611     {
612         CM_ASSERTMESSAGE("Error: Need to enable GT-Pin to call this function.");
613         return CM_NOT_IMPLEMENTED;
614     }
615 
616     if(kernIndex+1>m_surEntryInfoArrays.kernelNum)
617     {
618         CM_ASSERTMESSAGE("Error: Incorrect kernel Index.");
619         return CM_INVALID_ARG_VALUE;
620     }
621     uint32_t tempIndex=0;
622 
623     if (surfaceMgr->IsCmReservedSurfaceIndex(surfBTI))
624     {
625         tempIndex=surfBTI-CM_GLOBAL_SURFACE_INDEX_START;
626         if(tempIndex+1>m_surEntryInfoArrays.surfEntryInfosArray[kernIndex].globalSurfNum)
627         {
628             CM_ASSERTMESSAGE("Error: Incorrect surface Binding table Index.");
629             return CM_INVALID_ARG_VALUE;
630         }
631         tempSurfInfo = tempIndex +
632                         m_surEntryInfoArrays.surfEntryInfosArray[kernIndex].globalSurfInfos;
633 
634     }
635     else if (surfaceMgr->IsValidSurfaceIndex(surfBTI)) //not static buffer
636     {
637         if((surfBTI-surfaceMgr->ValidSurfaceIndexStart() +1)>m_surEntryInfoArrays.surfEntryInfosArray[kernIndex].usedIndex)
638         {
639             CM_ASSERTMESSAGE("Error: Incorrect surface Binding table Index.");
640             return CM_INVALID_ARG_VALUE;
641         }
642         else
643         {
644             tempIndex = surfBTI - surfaceMgr->ValidSurfaceIndexStart();
645         }
646         tempSurfInfo = tempIndex +
647                     m_surEntryInfoArrays.surfEntryInfosArray[kernIndex].surfEntryInfos;
648 
649     }
650     else
651     {//error
652         CM_ASSERTMESSAGE("Error: Incorrect surface Binding table Index.");
653         return CM_INVALID_ARG_VALUE;
654     }
655 
656     CmSafeMemCopy(&outDetails,tempSurfInfo,sizeof(CM_SURFACE_DETAILS));
657     return CM_SUCCESS;
658 }
659 
660 //*-----------------------------------------------------------------------------
661 //| Purpose:    GT-PIN : Set Surface Details
662 //| Returns:    Result of the operation.
663 //*-----------------------------------------------------------------------------
SetSurfaceDetails(CM_HAL_SURFACE_ENTRY_INFO_ARRAYS surfaceInfo)664 int32_t CmEventRT::SetSurfaceDetails(CM_HAL_SURFACE_ENTRY_INFO_ARRAYS surfaceInfo)
665 {
666     m_surEntryInfoArrays.kernelNum = surfaceInfo.kernelNum;
667     m_surEntryInfoArrays.surfEntryInfosArray = (CM_HAL_SURFACE_ENTRY_INFO_ARRAY*)MOS_AllocAndZeroMemory(
668                                                                    surfaceInfo.kernelNum *
669                                                                    sizeof(CM_HAL_SURFACE_ENTRY_INFO_ARRAY));
670 
671     if(m_surEntryInfoArrays.surfEntryInfosArray == nullptr)
672     {
673         CM_ASSERTMESSAGE("Error: Mem allocation fail.");
674         return CM_OUT_OF_HOST_MEMORY;
675     }
676 
677     for( uint32_t i = 0; i < surfaceInfo.kernelNum; i ++ )
678     {
679         //non static buffers
680         uint32_t surfEntryMax = surfaceInfo.surfEntryInfosArray[i].maxEntryNum;
681         uint32_t surfEntryNum = surfaceInfo.surfEntryInfosArray[i].usedIndex;
682 
683         m_surEntryInfoArrays.surfEntryInfosArray[i].usedIndex = surfEntryNum;
684         m_surEntryInfoArrays.surfEntryInfosArray[i].maxEntryNum = surfEntryMax;
685         CM_SURFACE_DETAILS* temp = (CM_SURFACE_DETAILS*)MOS_AllocAndZeroMemory(
686                                             surfEntryNum*
687                                             sizeof(CM_SURFACE_DETAILS));
688         if(temp == nullptr)
689         {
690             return CM_OUT_OF_HOST_MEMORY;
691          }
692         else
693         {
694             m_surEntryInfoArrays.surfEntryInfosArray[i].surfEntryInfos=temp;
695             CmSafeMemCopy(m_surEntryInfoArrays.surfEntryInfosArray[i].surfEntryInfos,
696                                          surfaceInfo.surfEntryInfosArray[i].surfEntryInfos,
697                                          surfEntryNum*sizeof(CM_SURFACE_DETAILS));
698          }
699 
700         //static buffers
701         uint32_t globalSurfNum = surfaceInfo.surfEntryInfosArray[i].globalSurfNum;
702         if(globalSurfNum>0)
703         {
704             m_surEntryInfoArrays.surfEntryInfosArray[i].globalSurfNum = globalSurfNum;
705             temp=(CM_SURFACE_DETAILS*)MOS_AllocAndZeroMemory(
706                   globalSurfNum*sizeof(CM_SURFACE_DETAILS));
707             if(temp == nullptr)
708             {
709                 return CM_OUT_OF_HOST_MEMORY;
710              }
711             else
712             {
713                 m_surEntryInfoArrays.surfEntryInfosArray[i].globalSurfInfos=temp;
714                 CmSafeMemCopy(m_surEntryInfoArrays.surfEntryInfosArray[i].globalSurfInfos,
715                                              surfaceInfo.surfEntryInfosArray[i].globalSurfInfos,
716                                              globalSurfNum*sizeof(CM_SURFACE_DETAILS));
717              }
718         }//(globalSurfNum>0)
719     }//for
720     return CM_SUCCESS;
721 }
722 
GetProfilingInfo(CM_EVENT_PROFILING_INFO infoType,size_t paramSize,void * inputValue,void * value)723 CM_RT_API  int32_t CmEventRT::GetProfilingInfo(CM_EVENT_PROFILING_INFO infoType, size_t paramSize, void  *inputValue, void  *value)
724 {
725     int32_t hr = CM_SUCCESS;
726 
727     CM_CHK_NULL_GOTOFINISH_CMERROR(value);
728 
729     switch(infoType)
730     {
731         case CM_EVENT_PROFILING_HWSTART:
732              CM_CHK_COND_RETURN((paramSize < sizeof(LARGE_INTEGER)), CM_INVALID_PARAM_SIZE, "Invalid parameter size.");
733              CM_CHK_CMSTATUS_GOTOFINISH(GetHWStartTime((LARGE_INTEGER *)value));
734              break;
735 
736         case CM_EVENT_PROFILING_HWEND:
737              CM_CHK_COND_RETURN((paramSize < sizeof(LARGE_INTEGER)), CM_INVALID_PARAM_SIZE, "Invalid parameter size.");
738              CM_CHK_CMSTATUS_GOTOFINISH(GetHWEndTime((LARGE_INTEGER *)value));
739              break;
740 
741         case CM_EVENT_PROFILING_SUBMIT:
742              CM_CHK_COND_RETURN((paramSize < sizeof(LARGE_INTEGER)), CM_INVALID_PARAM_SIZE, "Invalid parameter size.");
743              CM_CHK_CMSTATUS_GOTOFINISH(GetSubmitTime((LARGE_INTEGER *)value));
744              break;
745 
746         case CM_EVENT_PROFILING_COMPLETE:
747             CM_CHK_COND_RETURN((paramSize < sizeof(LARGE_INTEGER)), CM_INVALID_PARAM_SIZE, "Invalid parameter size.");
748              CM_CHK_CMSTATUS_GOTOFINISH(GetCompleteTime((LARGE_INTEGER *)value));
749              break;
750 
751         case CM_EVENT_PROFILING_ENQUEUE:
752             CM_CHK_COND_RETURN((paramSize < sizeof(LARGE_INTEGER)), CM_INVALID_PARAM_SIZE, "Invalid parameter size.");
753              CM_CHK_CMSTATUS_GOTOFINISH(GetEnqueueTime((LARGE_INTEGER *)value));
754              break;
755 
756         case CM_EVENT_PROFILING_KERNELCOUNT:
757              CM_CHK_COND_RETURN((paramSize < sizeof(uint32_t)), CM_INVALID_PARAM_SIZE, "Invalid parameter size.");
758              *(uint32_t *)value =  GetKernelCount();
759              break;
760 
761         case CM_EVENT_PROFILING_KERNELNAMES:
762              {
763                  CM_CHK_NULL_GOTOFINISH_CMERROR(inputValue);
764                  uint32_t kernelIndex = *(uint32_t *)inputValue;
765                  if( kernelIndex >= m_kernelCount)
766                  {
767                     hr = CM_INVALID_PARAM_SIZE;
768                     goto finish;
769                  }
770                  *((char **)value) = m_kernelNames[kernelIndex];
771              }
772              break;
773 
774         case CM_EVENT_PROFILING_THREADSPACE:
775              {
776                  CM_CHK_NULL_GOTOFINISH_CMERROR(inputValue);
777                  uint32_t kernelIndex = *(uint32_t *)inputValue;
778                  if( kernelIndex >= m_kernelCount)
779                  {
780                     hr = CM_INVALID_PARAM_SIZE;
781                     goto finish;
782                  }
783                  // 4 elements, global/local, width/height,
784                  CmSafeMemCopy(value, m_threadSpace + kernelIndex*4 , sizeof(uint32_t)*4);
785              }
786             break;
787 
788         case CM_EVENT_PROFILING_CALLBACK:
789             {
790                  CM_CHK_NULL_GOTOFINISH_CMERROR(inputValue);
791                  CM_CHK_NULL_GOTOFINISH_CMERROR(value);
792                  CM_CHK_CMSTATUS_GOTOFINISH(SetCallBack((EventCallBackFunction)inputValue, value));
793             }
794             break;
795 
796         default:
797             hr = CM_FAILURE;
798     }
799 
800 finish:
801     return hr;
802 }
803 
SetCallBack(EventCallBackFunction function,void * userData)804 int32_t CmEventRT:: SetCallBack(EventCallBackFunction function, void  *userData)
805 {
806     m_callbackFunction = function;
807     m_callbackUserData = userData;
808     return CM_SUCCESS;
809 }
810 
811 #if CM_LOG_ON
Log(const char * callerFuncName)812 std::string CmEventRT::Log(const char *callerFuncName)
813 {
814     static const char *statusStrings[] = {
815 #define ENUM_STRING(e)  #e
816             ENUM_STRING(CM_STATUS_QUEUED),
817             ENUM_STRING(CM_STATUS_FLUSHED),
818             ENUM_STRING(CM_STATUS_FINISHED),
819             ENUM_STRING(CM_STATUS_STARTED),
820             ENUM_STRING(CM_STATUS_RESET),
821 #undef ENUM_STRING
822     };
823 
824     std::ostringstream  oss;
825     oss << callerFuncName << "():\n"
826         << "<CmEvent>:" << reinterpret_cast<uint64_t>(this) << "\n"
827         << " Status: " << statusStrings[m_status] << "\n"
828         << " Duration:" << m_time << "ns\n"
829         << " DurationInTick:" << m_ticks << "\n"
830         << " StartTimeInTick:" << m_hwStartTimeStampInTicks << "\n"
831         << " EndTimeInTick:"<< m_hwEndTimeStampInTicks << "\n"
832         << " Kernel Cnt:"<< m_kernelCount << std::endl;
833 
834     return oss.str();
835 }
836 #endif
837 
838 }
839