1 /*
2 * Copyright (c) 2007-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_ftrace.cpp
24 //! \brief     Class Cm Ftrace definitions
25 //!
26 
27 #include "cm_ftrace.h"
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <string.h>
33 
34 #include "cm_task_internal.h"
35 
36 #define TRACE_MARKER_PATH "/sys/kernel/debug/tracing/trace_marker"
37 
38 #define TRACE_FLAG_PATH "/sys/kernel/debug/tracing/tracing_on"
39 
40 #define MSG_LENGTH 1024
41 
42 #define PRINT_TO_STRING(_fmt, _value)    \
43     byteInput = snprintf(msgBuf + byteOffset, MSG_LENGTH - byteOffset, _fmt, _value); \
44     byteOffset += byteInput;
45 
46 //Global static pointer to ensure a single instance
47 CmFtrace* CmFtrace::m_ftrace = nullptr;
48 
CmFtrace()49 CmFtrace::CmFtrace()
50 {
51     m_filehandle = open( TRACE_MARKER_PATH, O_WRONLY );
52 }
53 
~CmFtrace()54 CmFtrace::~CmFtrace()
55 {
56     if(m_filehandle >= 0)
57     {
58         close(m_filehandle);
59     }
60 }
61 
GetInstance()62 CmFtrace* CmFtrace::GetInstance()
63 {
64     if(m_ftrace == nullptr)
65     {
66         m_ftrace = new (std::nothrow) CmFtrace();
67     }
68 
69     return m_ftrace;
70 }
71 
WriteTaskProfilingInfo(CM_PROFILING_INFO * taskInfo)72 void CmFtrace::WriteTaskProfilingInfo(CM_PROFILING_INFO *taskInfo)
73 {
74     if(taskInfo == nullptr)
75     {
76         return ;
77     }
78 
79     char msgBuf[MSG_LENGTH];
80     uint byteOffset = 0;
81     uint byteInput = 0;
82 
83     PRINT_TO_STRING("%s: ", "mdf_v1")
84     PRINT_TO_STRING("kernelcount=%d|", taskInfo->kernelCount);
85     PRINT_TO_STRING("taskid=%d|",      taskInfo->taskID);
86     PRINT_TO_STRING("threadid=%u|",    taskInfo->threadID);
87 
88     uint kernelNameOffset = 0;
89     for(uint i=0 ; i< taskInfo->kernelCount; i++)
90     {
91         //Kernel name.
92         char *kernelname = taskInfo->kernelNames + kernelNameOffset;
93         PRINT_TO_STRING("kernelname=%s|", kernelname);
94         kernelNameOffset += strlen(kernelname) + 1;
95 
96         //Local work width&height
97         PRINT_TO_STRING("localwidth=%d|", taskInfo->localWorkWidth[i]);
98         PRINT_TO_STRING("localheight=%d|", taskInfo->localWorkHeight[i]);
99 
100         //Global work width&height
101         PRINT_TO_STRING("globalwidth=%d|",  taskInfo->globalWorkWidth[i]);
102         PRINT_TO_STRING("globalheight=%d|", taskInfo->globalWorkHeight[i]);
103     }
104 
105     //Note: enqueuetime/flushtime/completetime are measured in performance counter
106     //Don't need to convert to nanosec on Linux since MosUtilities::MosQueryPerformanceFrequency returns 1
107     //On linux, we can't get the gpu ticks when the command submitted, so that
108     //we can't do the adjustment the ticks b/w cpu and gpu, as what we did on windoes by GetGpuTime
109     //hw_start_time = flush_time; hw_end_time = hw_start_time + kernel_execution_time
110 
111     LARGE_INTEGER kernelExeTime;
112     kernelExeTime.QuadPart = taskInfo->hwEndTime.QuadPart - taskInfo->hwStartTime.QuadPart;
113 
114     //write time stampes
115     PRINT_TO_STRING("enqueuetime=%lld|",   (long long)taskInfo->enqueueTime.QuadPart);
116     PRINT_TO_STRING("flushtime=%lld|",     (long long)taskInfo->flushTime.QuadPart);
117     PRINT_TO_STRING("hwstarttime=%lld|",   (long long)taskInfo->flushTime.QuadPart);
118     PRINT_TO_STRING("hwendtime=%lld|",     (long long)(taskInfo->flushTime.QuadPart + kernelExeTime.QuadPart) );
119     PRINT_TO_STRING("completetime=%lld\n", (long long)taskInfo->completeTime.QuadPart);
120 
121     // write message to trace_marker
122     size_t writeSize = write(m_filehandle, msgBuf, byteOffset);
123 
124     return;
125 }
126