xref: /aosp_15_r20/external/intel-media-driver/media_softlet/agnostic/common/os/mos_utilities_next.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2019-2023, 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     mos_utilities_next.cpp
24 //! \brief    Common OS service across different platform
25 //! \details  Common OS service across different platform
26 //!
27 
28 #include <fcntl.h>
29 #include <math.h>
30 #include "mos_os.h"
31 #include "mos_utilities_specific.h"
32 
33 int32_t              MosUtilities::m_mosMemAllocCounterNoUserFeature    = 0;
34 int32_t              MosUtilities::m_mosMemAllocCounterNoUserFeatureGfx = 0;
35 const MtControlData *MosUtilities::m_mosTraceControlData                = nullptr;
36 MtEnable             MosUtilities::m_mosTraceEnable                     = false;
37 MtFilter             MosUtilities::m_mosTraceFilter                     = {};
38 MtLevel              MosUtilities::m_mosTraceLevel                      = {};
39 
MosGetCurTime()40 uint64_t MosUtilities::MosGetCurTime()
41 {
42     using us = std::chrono::microseconds;
43     using clock = std::chrono::steady_clock;
44 
45     clock::time_point Timer = clock::now();
46     uint64_t usStartTime =
47             std::chrono::duration_cast<us>(Timer.time_since_epoch()).count();
48 
49     return usStartTime;
50 }
51 
52 #if (_DEBUG || _RELEASE_INTERNAL)
53 
54 uint32_t MosUtilities::m_mosAllocMemoryFailSimulateMode = 0;
55 uint32_t MosUtilities::m_mosAllocMemoryFailSimulateFreq = 0;
56 uint32_t MosUtilities::m_mosAllocMemoryFailSimulateHint = 0;
57 
MosInitAllocMemoryFailSimulateFlag(MediaUserSettingSharedPtr userSettingPtr)58 void MosUtilities::MosInitAllocMemoryFailSimulateFlag(MediaUserSettingSharedPtr userSettingPtr)
59 {
60     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
61     uint32_t   value   = 0;
62 
63     //default off for simulate random fail
64     m_mosAllocMemoryFailSimulateMode = MEMORY_ALLOC_FAIL_SIMULATE_MODE_DEFAULT;
65     m_mosAllocMemoryFailSimulateFreq = 0;
66     m_mosAllocMemoryFailSimulateHint = 0;
67     if (m_mosAllocMemoryFailSimulateAllocCounter != nullptr)
68     {
69         *m_mosAllocMemoryFailSimulateAllocCounter = 0;
70     }
71     else
72     {
73         MOS_OS_ASSERTMESSAGE("SimulateAllocCounter is nullptr");
74     }
75     // Read Config : memory allocation failure simulate mode
76     ReadUserSetting(
77         userSettingPtr,
78         value,
79         __MEDIA_USER_FEATURE_VALUE_ALLOC_MEMORY_FAIL_SIMULATE_MODE,
80         MediaUserSetting::Group::Device);
81 
82     if ((value == MEMORY_ALLOC_FAIL_SIMULATE_MODE_DEFAULT) ||
83         (value == MEMORY_ALLOC_FAIL_SIMULATE_MODE_RANDOM) ||
84         (value == MEMORY_ALLOC_FAIL_SIMULATE_MODE_TRAVERSE))
85     {
86         m_mosAllocMemoryFailSimulateMode = value;
87         MOS_OS_NORMALMESSAGE("Init MosSimulateAllocMemoryFailSimulateMode as %d \n ", m_mosAllocMemoryFailSimulateMode);
88     }
89     else
90     {
91         m_mosAllocMemoryFailSimulateMode = MEMORY_ALLOC_FAIL_SIMULATE_MODE_DEFAULT;
92         MOS_OS_NORMALMESSAGE("Invalid Alloc Memory Fail Simulate Mode from config: %d \n ", value);
93     }
94 
95     // Read Config : memory allocation failure simulate frequence
96     value = 0;
97     ReadUserSetting(
98         userSettingPtr,
99         value,
100         __MEDIA_USER_FEATURE_VALUE_ALLOC_MEMORY_FAIL_SIMULATE_FREQ,
101         MediaUserSetting::Group::Device);
102 
103     if ((value >= MIN_MEMORY_ALLOC_FAIL_FREQ) &&
104         (value <= MAX_MEMORY_ALLOC_FAIL_FREQ))
105     {
106         m_mosAllocMemoryFailSimulateFreq = value;
107         MOS_OS_NORMALMESSAGE("Init m_MosSimulateRandomAllocMemoryFailFreq as %d \n ", m_mosAllocMemoryFailSimulateFreq);
108 
109         if (m_mosAllocMemoryFailSimulateMode == MEMORY_ALLOC_FAIL_SIMULATE_MODE_RANDOM)
110         {
111             srand((unsigned int)time(nullptr));
112         }
113     }
114     else
115     {
116         m_mosAllocMemoryFailSimulateFreq = 0;
117         MOS_OS_NORMALMESSAGE("Invalid Alloc Memory Fail Simulate Freq from config: %d \n ", value);
118     }
119 
120     // Read Config : memory allocation failure simulate counter
121     value = 0;
122     ReadUserSetting(
123         userSettingPtr,
124         value,
125         __MEDIA_USER_FEATURE_VALUE_ALLOC_MEMORY_FAIL_SIMULATE_HINT,
126         MediaUserSetting::Group::Device);
127     if (value <= m_mosAllocMemoryFailSimulateFreq)
128     {
129         m_mosAllocMemoryFailSimulateHint = value;
130         MOS_OS_NORMALMESSAGE("Init m_MosAllocMemoryFailSimulateHint as %d \n ", m_mosAllocMemoryFailSimulateHint);
131     }
132     else
133     {
134         m_mosAllocMemoryFailSimulateHint = m_mosAllocMemoryFailSimulateFreq;
135         MOS_OS_NORMALMESSAGE("Set m_mosAllocMemoryFailSimulateHint as %d since INVALID CONFIG %d \n ", m_mosAllocMemoryFailSimulateHint, value);
136     }
137 }
138 
MosSimulateAllocMemoryFail(size_t size,size_t alignment,const char * functionName,const char * filename,int32_t line)139 bool MosUtilities::MosSimulateAllocMemoryFail(
140     size_t      size,
141     size_t      alignment,
142     const char *functionName,
143     const char *filename,
144     int32_t     line)
145 {
146     bool bSimulateAllocFail = false;
147 
148     if (!MosAllocMemoryFailSimulationEnabled)
149     {
150         return false;
151     }
152 
153     if (m_mosAllocMemoryFailSimulateMode == MEMORY_ALLOC_FAIL_SIMULATE_MODE_RANDOM)
154     {
155         int32_t Rn = rand();
156         MosAtomicIncrement(m_mosAllocMemoryFailSimulateAllocCounter);
157         if (Rn % m_mosAllocMemoryFailSimulateFreq == 1)
158         {
159             bSimulateAllocFail = true;
160             MOS_DEBUGMESSAGE(MOS_MESSAGE_LVL_CRITICAL, MOS_COMPONENT_OS, MOS_SUBCOMP_SELF, "Simulated Allocate Memory Fail (Rn=%d, SimulateAllocCounter=%d) for: functionName: %s, filename: %s, line: %d, size: %d, alignment: %d \n", Rn, (m_mosAllocMemoryFailSimulateAllocCounter ? *m_mosAllocMemoryFailSimulateAllocCounter : 0), functionName, filename, line, size, alignment);
161         }
162         else
163         {
164             bSimulateAllocFail = false;
165         }
166     }
167     else if (m_mosAllocMemoryFailSimulateMode == MEMORY_ALLOC_FAIL_SIMULATE_MODE_TRAVERSE)
168     {
169         if (m_mosAllocMemoryFailSimulateAllocCounter &&
170             (*m_mosAllocMemoryFailSimulateAllocCounter == m_mosAllocMemoryFailSimulateHint))
171         {
172             MOS_DEBUGMESSAGE(MOS_MESSAGE_LVL_CRITICAL, MOS_COMPONENT_OS, MOS_SUBCOMP_SELF, "Simulated Allocate Memory Fail (hint=%d) for: functionName: %s, filename: %s, line: %d, size: %d \n", m_mosAllocMemoryFailSimulateHint, functionName, filename, line, size, alignment);
173             bSimulateAllocFail = true;
174         }
175         else
176         {
177             bSimulateAllocFail = false;
178         }
179         MosAtomicIncrement(m_mosAllocMemoryFailSimulateAllocCounter);
180     }
181     else
182     {
183         MOS_OS_NORMALMESSAGE("Invalid m_MosAllocMemoryFailSimulateMode: %d \n ", m_mosAllocMemoryFailSimulateMode);
184         bSimulateAllocFail = false;
185     }
186 
187     return bSimulateAllocFail;
188 }
189 #endif  // #if (_DEBUG || _RELEASE_INTERNAL)
190 
191 #if MOS_MESSAGES_ENABLED
MosAlignedAllocMemoryUtils(size_t size,size_t alignment,const char * functionName,const char * filename,int32_t line)192 void *MosUtilities::MosAlignedAllocMemoryUtils(
193     size_t      size,
194     size_t      alignment,
195     const char  *functionName,
196     const char  *filename,
197     int32_t     line)
198 #else
199 void  *MosUtilities::MosAlignedAllocMemory(
200     size_t  size,
201     size_t  alignment)
202 #endif // MOS_MESSAGES_ENABLED
203 {
204     void  *ptr;
205 
206 #if (_DEBUG || _RELEASE_INTERNAL)
207     if (MosSimulateAllocMemoryFail(size, alignment, functionName, filename, line))
208     {
209         return nullptr;
210     }
211 #endif
212 
213     ptr = _aligned_malloc(size, alignment);
214 
215     MOS_OS_ASSERT(ptr != nullptr);
216 
217     if(ptr != nullptr)
218     {
219         MosAtomicIncrement(m_mosMemAllocCounter);
220         MOS_MEMNINJA_ALLOC_MESSAGE(ptr, size, functionName, filename, line);
221         PRINT_ALLOCATE_MEMORY(MT_MOS_ALLOCATE_MEMORY, MT_NORMAL,
222                 MT_MEMORY_PTR, (int64_t)(ptr),
223                 MT_MEMORY_SIZE, static_cast<int64_t>(size),
224                 functionName, filename, line);
225     }
226 
227     return ptr;
228 }
229 
230 #if MOS_MESSAGES_ENABLED
MosAlignedFreeMemoryUtils(void * ptr,const char * functionName,const char * filename,int32_t line)231 void MosUtilities::MosAlignedFreeMemoryUtils(
232     void        *ptr,
233     const char  *functionName,
234     const char  *filename,
235     int32_t     line)
236 #else
237 void MosUtilities::MosAlignedFreeMemory(void *ptr)
238 #endif // MOS_MESSAGES_ENABLED
239 {
240     MOS_OS_ASSERT(ptr != nullptr);
241 
242     if(ptr != nullptr)
243     {
244         MosAtomicDecrement(m_mosMemAllocCounter);
245         MOS_MEMNINJA_FREE_MESSAGE(ptr, functionName, filename, line);
246         PRINT_DESTROY_MEMORY(MT_MOS_DESTROY_MEMORY, MT_NORMAL,
247                 MT_MEMORY_PTR, (int64_t)(ptr),
248                 functionName, filename, line);
249         _aligned_free(ptr);
250     }
251 }
252 
253 #if MOS_MESSAGES_ENABLED
MosAllocMemoryUtils(size_t size,const char * functionName,const char * filename,int32_t line)254 void *MosUtilities::MosAllocMemoryUtils(
255     size_t      size,
256     const char  *functionName,
257     const char  *filename,
258     int32_t     line)
259 #else
260 void *MosUtilities::MosAllocMemory(size_t size)
261 #endif // MOS_MESSAGES_ENABLED
262 {
263     void  *ptr;
264 
265 #if (_DEBUG || _RELEASE_INTERNAL)
266     if (MosSimulateAllocMemoryFail(size, NO_ALLOC_ALIGNMENT, functionName, filename, line))
267     {
268         return nullptr;
269     }
270 #endif
271 
272     ptr = malloc(size);
273 
274     MOS_OS_ASSERT(ptr != nullptr);
275 
276     if(ptr != nullptr)
277     {
278         MosAtomicIncrement(m_mosMemAllocCounter);
279         MOS_MEMNINJA_ALLOC_MESSAGE(ptr, size, functionName, filename, line);
280         PRINT_ALLOCATE_MEMORY(MT_MOS_ALLOCATE_MEMORY, MT_NORMAL,
281                 MT_MEMORY_PTR, (int64_t)(ptr),
282                 MT_MEMORY_SIZE, static_cast<int64_t>(size),
283                 functionName, filename, line);
284     }
285 
286     return ptr;
287 }
288 
289 #if MOS_MESSAGES_ENABLED
MosAllocAndZeroMemoryUtils(size_t size,const char * functionName,const char * filename,int32_t line)290 void *MosUtilities::MosAllocAndZeroMemoryUtils(
291     size_t      size,
292     const char  *functionName,
293     const char  *filename,
294     int32_t     line)
295 #else
296 void *MosUtilities::MosAllocAndZeroMemory(size_t size)
297 #endif // MOS_MESSAGES_ENABLED
298 {
299     void  *ptr;
300 
301 #if (_DEBUG || _RELEASE_INTERNAL)
302     if (MosSimulateAllocMemoryFail(size, NO_ALLOC_ALIGNMENT, functionName, filename, line))
303     {
304         return nullptr;
305     }
306 #endif
307 
308     ptr = malloc(size);
309 
310     MOS_OS_ASSERT(ptr != nullptr);
311 
312     if(ptr != nullptr)
313     {
314         MosZeroMemory(ptr, size);
315 
316         MosAtomicIncrement(m_mosMemAllocCounter);
317         MOS_MEMNINJA_ALLOC_MESSAGE(ptr, size, functionName, filename, line);
318         PRINT_ALLOCATE_MEMORY(MT_MOS_ALLOCATE_MEMORY, MT_NORMAL,
319                 MT_MEMORY_PTR, (int64_t)(ptr),
320                 MT_MEMORY_SIZE, static_cast<int64_t>(size),
321                 functionName, filename, line);
322     }
323 
324     return ptr;
325 }
326 
327 #if MOS_MESSAGES_ENABLED
MosReallocMemoryUtils(void * ptr,size_t newSize,const char * functionName,const char * filename,int32_t line)328 void *MosUtilities::MosReallocMemoryUtils(
329     void       *ptr,
330     size_t     newSize,
331     const char *functionName,
332     const char *filename,
333     int32_t    line)
334 #else
335 void *MosUtilities::MosReallocMemory(
336     void       *ptr,
337     size_t     newSize)
338 #endif // MOS_MESSAGES_ENABLED
339 {
340     uintptr_t oldPtr = reinterpret_cast<uintptr_t>(nullptr);
341     void *newPtr = nullptr;
342 
343 #if (_DEBUG || _RELEASE_INTERNAL)
344     if (MosSimulateAllocMemoryFail(newSize, NO_ALLOC_ALIGNMENT, functionName, filename, line))
345     {
346         return nullptr;
347     }
348 #endif
349 
350     oldPtr = reinterpret_cast<uintptr_t>(ptr);
351     newPtr = realloc(ptr, newSize);
352 
353     MOS_OS_ASSERT(newPtr != nullptr);
354 
355     if (newPtr != reinterpret_cast<void*>(oldPtr))
356     {
357         if (oldPtr != reinterpret_cast<uintptr_t>(nullptr))
358         {
359             MosAtomicDecrement(m_mosMemAllocCounter);
360             MOS_MEMNINJA_FREE_MESSAGE(oldPtr, functionName, filename, line);
361             PRINT_DESTROY_MEMORY(MT_MOS_DESTROY_MEMORY, MT_NORMAL,
362                 MT_MEMORY_PTR, (int64_t)(oldPtr),
363                 functionName, filename, line);
364         }
365 
366         if (newPtr != nullptr)
367         {
368             MosAtomicIncrement(m_mosMemAllocCounter);
369             MOS_MEMNINJA_ALLOC_MESSAGE(newPtr, newSize, functionName, filename, line);
370             PRINT_ALLOCATE_MEMORY(MT_MOS_ALLOCATE_MEMORY, MT_NORMAL,
371                 MT_MEMORY_PTR, (int64_t)(newPtr),
372                 MT_MEMORY_SIZE, static_cast<int64_t>(newSize),
373                 functionName, filename, line);
374         }
375     }
376 
377     return newPtr;
378 }
379 
380 //!
381 //! \brief    Wrapper for free(). Performs error checking.
382 //! \details  Wrapper for free(). Performs error checking.
383 //!           It decreases memory allocation counter variable
384 //!           m_mosMemAllocCounter for checking memory leaks.
385 //! \param    void  *ptr
386 //!           [in] Pointer to the memory to be freed
387 //! \return   void
388 //!
389 #if MOS_MESSAGES_ENABLED
MosFreeMemoryUtils(void * ptr,const char * functionName,const char * filename,int32_t line)390 void MosUtilities::MosFreeMemoryUtils(
391     void        *ptr,
392     const char  *functionName,
393     const char  *filename,
394     int32_t     line)
395 #else
396 void MosUtilities::MosFreeMemory(void  *ptr)
397 #endif // MOS_MESSAGES_ENABLED
398 {
399     if(ptr != nullptr)
400     {
401         MosAtomicDecrement(m_mosMemAllocCounter);
402         MOS_MEMNINJA_FREE_MESSAGE(ptr, functionName, filename, line);
403         PRINT_DESTROY_MEMORY(MT_MOS_DESTROY_MEMORY, MT_NORMAL,
404             MT_MEMORY_PTR, (int64_t)(ptr),
405             functionName, filename, line);
406         free(ptr);
407         ptr = nullptr;
408     }
409 }
410 
MosZeroMemory(void * pDestination,size_t stLength)411 void MosUtilities::MosZeroMemory(void  *pDestination, size_t stLength)
412 {
413     MOS_OS_ASSERT(pDestination != nullptr);
414 
415     if(pDestination != nullptr)
416     {
417         memset(pDestination, 0, stLength);
418     }
419 }
420 
MosFillMemory(void * pDestination,size_t stLength,uint8_t bFill)421 void MosUtilities::MosFillMemory(void  *pDestination, size_t stLength, uint8_t bFill)
422 {
423     MOS_OS_ASSERT(pDestination != nullptr);
424 
425     if(pDestination != nullptr)
426     {
427         memset(pDestination, bFill, stLength);
428     }
429 }
430 
MosReadFileToPtr(const char * pFilename,uint32_t * lpNumberOfBytesRead,void ** ppReadBuffer)431 MOS_STATUS  MosUtilities::MosReadFileToPtr(
432     const char      *pFilename,
433     uint32_t        *lpNumberOfBytesRead,
434     void            **ppReadBuffer)
435 {
436     HANDLE          hFile;
437     void            *lpBuffer;
438     uint32_t        fileSize;
439     uint32_t        bytesRead;
440     MOS_STATUS      eStatus;
441 
442     *ppReadBuffer = nullptr;
443     *lpNumberOfBytesRead = 0;
444 
445     eStatus = MosCreateFile(&hFile, (char *)pFilename, O_RDONLY);
446 
447     if (eStatus != MOS_STATUS_SUCCESS)
448     {
449         MOS_OS_ASSERTMESSAGE("Failed to open file '%s'.", pFilename);
450         return eStatus;
451     }
452 
453     eStatus = MosGetFileSize(hFile, &fileSize, nullptr);
454 
455     if (eStatus != MOS_STATUS_SUCCESS)
456     {
457         MOS_OS_ASSERTMESSAGE("Failed to get size of file '%s'.", pFilename);
458         MosCloseHandle(hFile);
459         return eStatus;
460     }
461 
462     lpBuffer = MOS_AllocAndZeroMemory(fileSize);
463     if (lpBuffer == nullptr)
464     {
465         MOS_OS_ASSERTMESSAGE("Failed to allocate memory.");
466         MosCloseHandle(hFile);
467         return MOS_STATUS_NO_SPACE;
468     }
469 
470     if((eStatus = MosReadFile(hFile, lpBuffer, fileSize, &bytesRead, nullptr)) != MOS_STATUS_SUCCESS)
471     {
472         MOS_OS_ASSERTMESSAGE("Failed to read from file '%s'.", pFilename);
473         MosCloseHandle(hFile);
474         MOS_FreeMemory(lpBuffer);
475         lpBuffer = nullptr;
476         return eStatus;
477     }
478 
479     MosCloseHandle(hFile);
480     *lpNumberOfBytesRead = bytesRead;
481     *ppReadBuffer = lpBuffer;
482     return eStatus;
483 }
484 
MosWriteFileFromPtr(const char * pFilename,void * lpBuffer,uint32_t writeSize)485 MOS_STATUS MosUtilities::MosWriteFileFromPtr(
486     const char      *pFilename,
487     void            *lpBuffer,
488     uint32_t        writeSize)
489 {
490     HANDLE          hFile;
491     uint32_t        bytesWritten;
492     MOS_STATUS      eStatus;
493 
494     MOS_OS_CHK_NULL_RETURN(pFilename);
495     MOS_OS_CHK_NULL_RETURN(lpBuffer);
496 
497     if (writeSize == 0)
498     {
499         MOS_OS_ASSERTMESSAGE("Attempting to write 0 bytes to a file");
500         eStatus = MOS_STATUS_INVALID_PARAMETER;
501         return eStatus;
502     }
503 
504     bytesWritten    = 0;
505 
506     eStatus = MosCreateFile(&hFile, (char *)pFilename, O_WRONLY|O_CREAT);
507 
508     if (eStatus != MOS_STATUS_SUCCESS)
509     {
510         MOS_OS_ASSERTMESSAGE("Failed to open file '%s'.", pFilename);
511         return eStatus;
512     }
513 
514     if((eStatus = MosWriteFile(hFile, lpBuffer, writeSize, &bytesWritten, nullptr)) != MOS_STATUS_SUCCESS)
515     {
516         MOS_OS_ASSERTMESSAGE("Failed to write to file '%s'.", pFilename);
517         MosCloseHandle(hFile);
518         return eStatus;
519     }
520 
521     MosCloseHandle(hFile);
522 
523     return eStatus;
524 }
525 
MosAppendFileFromPtr(const char * pFilename,void * pData,uint32_t dwSize)526 MOS_STATUS MosUtilities::MosAppendFileFromPtr(
527     const char      *pFilename,
528     void            *pData,
529     uint32_t        dwSize)
530 {
531     MOS_STATUS  eStatus;
532     HANDLE      hFile;
533     uint32_t    dwWritten;
534 
535     //------------------------------
536     MOS_OS_ASSERT(pFilename);
537     MOS_OS_ASSERT(pData);
538     //------------------------------
539     dwWritten   = 0;
540 
541     eStatus = MosCreateFile(&hFile, (char *)pFilename, O_WRONLY | O_CREAT | O_APPEND);
542     if (eStatus != MOS_STATUS_SUCCESS)
543     {
544         MOS_OS_ASSERTMESSAGE("Failed to open file '%s'.", pFilename);
545         return eStatus;
546     }
547 
548     eStatus = MosSetFilePointer(hFile, 0, nullptr, SEEK_END);
549     if (eStatus != MOS_STATUS_SUCCESS)
550     {
551         MOS_OS_ASSERTMESSAGE("Failed to set file pointer'%s'.", pFilename);
552         MosCloseHandle(hFile);
553         return eStatus;
554     }
555 
556     // Write the file
557     if((eStatus = MosWriteFile(hFile, pData, dwSize, &dwWritten, nullptr)) != MOS_STATUS_SUCCESS)
558     {
559         MOS_OS_ASSERTMESSAGE("Failed to write to file '%s'.", pFilename);
560         MosCloseHandle(hFile);
561         return eStatus;
562     }
563 
564     MosCloseHandle(hFile);
565     return eStatus;
566 }
567 
MosSinc(float x)568 float MosUtilities::MosSinc(float x)
569 {
570     return (MOS_ABS(x) < 1e-9f) ? 1.0F : (float)(sin(x) / x);
571 }
572 
MosLanczos(float x,uint32_t dwNumEntries,float fLanczosT)573 float MosUtilities::MosLanczos(float x, uint32_t dwNumEntries, float fLanczosT)
574 {
575     uint32_t dwNumHalfEntries;
576 
577     dwNumHalfEntries = dwNumEntries >> 1;
578     if (fLanczosT < dwNumHalfEntries)
579     {
580         fLanczosT = (float)dwNumHalfEntries;
581     }
582 
583     if (MOS_ABS(x) >= dwNumHalfEntries)
584     {
585         return 0.0;
586     }
587 
588     x *= MOS_PI;
589 
590     return MosSinc(x) * MosSinc(x / fLanczosT);
591 }
592 
MosLanczosG(float x,uint32_t dwNumEntries,float fLanczosT)593 float MosUtilities::MosLanczosG(float x, uint32_t dwNumEntries, float fLanczosT)
594 {
595     uint32_t dwNumHalfEntries;
596 
597     dwNumHalfEntries = (dwNumEntries >> 1) + (dwNumEntries & 1);
598     if (fLanczosT < dwNumHalfEntries)
599     {
600         fLanczosT = (float)dwNumHalfEntries;
601     }
602 
603     if (x > (dwNumEntries >> 1) || (- x) >= dwNumHalfEntries)
604     {
605         return 0.0;
606     }
607 
608     x *= MOS_PI;
609 
610     return MosSinc(x) * MosSinc(x / fLanczosT);
611 }
612 
MosGCD(uint32_t a,uint32_t b)613 uint32_t MosUtilities::MosGCD(uint32_t a, uint32_t b)
614 {
615     if (b == 0)
616     {
617         return a;
618     }
619     else
620     {
621         return MosGCD(b, a % b);
622     }
623 }
624 
625 #ifdef _MOS_UTILITY_EXT
626 #include "mos_utilities_ext_next.h"
627 #else
628 #define Mos_SwizzleOffset MosUtilities::MosSwizzleOffset
629 #endif
630 
MosSwizzleOffset(int32_t OffsetX,int32_t OffsetY,int32_t Pitch,MOS_TILE_TYPE TileFormat,int32_t CsxSwizzle,int32_t ExtFlags)631 __inline int32_t MosUtilities::MosSwizzleOffset(
632     int32_t         OffsetX,
633     int32_t         OffsetY,
634     int32_t         Pitch,
635     MOS_TILE_TYPE   TileFormat,
636     int32_t         CsxSwizzle,
637     int32_t         ExtFlags)
638 {
639     // When dealing with a tiled surface, logical linear accesses to the
640     // surface (y * pitch + x) must be translated into appropriate tile-
641     // formated accesses--This is done by swizzling (rearranging/translating)
642     // the given access address--though it is important to note that the
643     // swizzling is actually done on the accessing OFFSET into a TILED
644     // REGION--not on the absolute address itself.
645 
646     // (!) Y-MAJOR TILING, REINTERPRETATION: For our purposes here, Y-Major
647     // tiling will be thought of in a different way, we will deal with
648     // the 16-byte-wide columns individually--i.e., we will treat a single
649     // Y-Major tile as 8 separate, thinner tiles--Doing so allows us to
650     // deal with both X- and Y-Major tile formats in the same "X-Major"
651     // way--just with different dimensions: either 512B x 8 rows, or
652     // 16B x 32 rows, respectively.
653 
654     // A linear offset into a surface is of the form
655     //     y * pitch + x   =   y:x (Shorthand, meaning: y * (x's per y) + x)
656     //
657     // To treat a surface as being composed of tiles (though still being
658     // linear), just as a linear offset has a y:x composition--its y and x
659     // components can be thought of as having Row:Line and Column:X
660     // compositions, respectively, where Row specifies a row of tiles, Line
661     // specifies a row of pixels within a tile, Column specifies a column
662     // of tiles, and X in this context refers to a byte within a Line--i.e.,
663     //     offset = y:x
664     //     y = Row:Line
665     //     x = Col:X
666     //     offset = y:x = Row:Line:Col:X
667 
668     // Given the Row:Line:Col:X composition of a linear offset, all that
669     // tile swizzling does is swap the Line and Col components--i.e.,
670     //     Linear Offset:   Row:Line:Col:X
671     //     Swizzled Offset: Row:Col:Line:X
672     // And with our reinterpretation of the Y-Major tiling format, we can now
673     // describe both the X- and Y-Major tiling formats in two simple terms:
674     // (1) The bit-depth of their Lines component--LBits, and (2) the
675     // swizzled bit-position of the Lines component (after it swaps with the
676     // Col component)--LPos.
677 
678     int32_t Row, Line, Col, x; // Linear Offset Components
679     int32_t LBits, LPos; // Size and swizzled position of the Line component.
680     int32_t SwizzledOffset;
681     if (TileFormat == MOS_TILE_LINEAR)
682     {
683         return(OffsetY * Pitch + OffsetX);
684     }
685 
686     if (TileFormat == MOS_TILE_Y)
687     {
688         LBits = 5; // Log2(TileY.Height = 32)
689         LPos = 4;  // Log2(TileY.PseudoWidth = 16)
690     }
691     else //if (TileFormat == MOS_TILE_X)
692     {
693         LBits = 3; // Log2(TileX.Height = 8)
694         LPos = 9;  // Log2(TileX.Width = 512)
695     }
696 
697     Row = OffsetY >> LBits;               // OffsetY / LinesPerTile
698     Line = OffsetY & ((1 << LBits) - 1);   // OffsetY % LinesPerTile
699     Col = OffsetX >> LPos;                // OffsetX / BytesPerLine
700     x = OffsetX & ((1 << LPos) - 1);    // OffsetX % BytesPerLine
701 
702     SwizzledOffset =
703         (((((Row * (Pitch >> LPos)) + Col) << LBits) + Line) << LPos) + x;
704     //                V                V                 V
705     //                / BytesPerLine   * LinesPerTile    * BytesPerLine
706 
707     /// Channel Select XOR Swizzling ///////////////////////////////////////////
708     if (CsxSwizzle)
709     {
710         if (TileFormat == MOS_TILE_Y) // A6 = A6 ^ A9
711         {
712             SwizzledOffset ^= ((SwizzledOffset >> (9 - 6)) & 0x40);
713         }
714         else //if (TileFormat == VPHAL_TILE_X) // A6 = A6 ^ A9 ^ A10
715         {
716             SwizzledOffset ^= (((SwizzledOffset >> (9 - 6)) ^ (SwizzledOffset >> (10 - 6))) & 0x40);
717         }
718     }
719 
720     return(SwizzledOffset);
721 }
722 
MosSwizzleOffsetWrapper(int32_t OffsetX,int32_t OffsetY,int32_t Pitch,MOS_TILE_TYPE TileFormat,int32_t CsxSwizzle,int32_t Flags)723 int32_t MosUtilities::MosSwizzleOffsetWrapper(
724     int32_t         OffsetX,
725     int32_t         OffsetY,
726     int32_t         Pitch,
727     MOS_TILE_TYPE   TileFormat,
728     int32_t         CsxSwizzle,
729     int32_t         Flags)
730 {
731     return Mos_SwizzleOffset(OffsetX, OffsetY, Pitch, TileFormat, CsxSwizzle, Flags);
732 }
733 
MosSwizzleData(uint8_t * pSrc,uint8_t * pDst,MOS_TILE_TYPE SrcTiling,MOS_TILE_TYPE DstTiling,int32_t iHeight,int32_t iPitch,int32_t extFlags)734 void MosUtilities::MosSwizzleData(
735     uint8_t         *pSrc,
736     uint8_t         *pDst,
737     MOS_TILE_TYPE   SrcTiling,
738     MOS_TILE_TYPE   DstTiling,
739     int32_t         iHeight,
740     int32_t         iPitch,
741     int32_t         extFlags)
742 {
743 
744 #define IS_TILED(_a)                ((_a) != MOS_TILE_LINEAR)
745 #define IS_TILED_TO_LINEAR(_a, _b)  (IS_TILED(_a) && !IS_TILED(_b))
746 #define IS_LINEAR_TO_TILED(_a, _b)  (!IS_TILED(_a) && IS_TILED(_b))
747 
748     int32_t LinearOffset;
749     int32_t TileOffset;
750     int32_t x;
751     int32_t y;
752 
753     // Translate from one format to another
754     for (y = 0, LinearOffset = 0, TileOffset = 0; y < iHeight; y++)
755     {
756         for (x = 0; x < iPitch; x++, LinearOffset++)
757         {
758             // x or y --> linear
759             if (IS_TILED_TO_LINEAR(SrcTiling, DstTiling))
760             {
761                 TileOffset = Mos_SwizzleOffset(
762                     x,
763                     y,
764                     iPitch,
765                     SrcTiling,
766                     false,
767                     extFlags);
768                 if(TileOffset < iHeight * iPitch)
769                     *(pDst + LinearOffset) = *(pSrc + TileOffset);
770             }
771             // linear --> x or y
772             else if (IS_LINEAR_TO_TILED(SrcTiling, DstTiling))
773             {
774                 TileOffset = Mos_SwizzleOffset(
775                     x,
776                     y,
777                     iPitch,
778                     DstTiling,
779                     false,
780                     extFlags);
781                 if(TileOffset < iHeight * iPitch)
782                     *(pDst + TileOffset) = *(pSrc + LinearOffset);
783             }
784             else
785             {
786                 MOS_OS_ASSERT(0);
787             }
788         }
789     }
790 }
791 
792 std::shared_ptr<PerfUtility> PerfUtility::instance = nullptr;
793 std::mutex PerfUtility::perfMutex;
794 PerfUtility* g_perfutility = PerfUtility::getInstance();
795 
getInstance()796 PerfUtility *PerfUtility::getInstance()
797 {
798     if (instance == nullptr)
799     {
800         instance = std::make_shared<PerfUtility>();
801     }
802 
803     return instance.get();
804 }
805 
PerfUtility()806 PerfUtility::PerfUtility()
807 {
808     bPerfUtilityKey = false;
809     dwPerfUtilityIsEnabled = 0;
810 }
811 
~PerfUtility()812 PerfUtility::~PerfUtility()
813 {
814     for (const auto &data : records)
815     {
816         if (data.second)
817         {
818             delete data.second;
819         }
820     }
821     records.clear();
822 }
823 
setupFilePath(const char * perfFilePath)824 void PerfUtility::setupFilePath(const char *perfFilePath)
825 {
826     int32_t pid = MosUtilities::MosGetPid();
827     MOS_SecureStringPrint(sSummaryFileName, MOS_MAX_PATH_LENGTH + 1, MOS_MAX_PATH_LENGTH + 1,
828         "%sperf_summary_pid%d.csv", perfFilePath, pid);
829     MOS_SecureStringPrint(sDetailsFileName, MOS_MAX_PATH_LENGTH + 1, MOS_MAX_PATH_LENGTH + 1,
830         "%sperf_details_pid%d.txt", perfFilePath, pid);
831 }
832 
setupFilePath()833 void PerfUtility::setupFilePath()
834 {
835     int32_t pid = MosUtilities::MosGetPid();
836     MOS_SecureStringPrint(sSummaryFileName, MOS_MAX_PATH_LENGTH + 1, MOS_MAX_PATH_LENGTH + 1,
837         "perf_summary_pid%d.csv", pid);
838     MOS_SecureStringPrint(sDetailsFileName, MOS_MAX_PATH_LENGTH + 1, MOS_MAX_PATH_LENGTH + 1,
839         "perf_details_pid%d.txt", pid);
840 }
841 
savePerfData()842 void PerfUtility::savePerfData()
843 {
844     printPerfSummary();
845 
846     printPerfDetails();
847 }
848 
printPerfSummary()849 void PerfUtility::printPerfSummary()
850 {
851     std::ofstream fout;
852     fout.open(sSummaryFileName);
853     if(fout.good() == false)
854     {
855         fout.close();
856         return;
857     }
858     printHeader(fout);
859     printBody(fout);
860     fout.close();
861     return;
862 }
863 
printPerfDetails()864 void PerfUtility::printPerfDetails()
865 {
866     std::ofstream fout;
867     fout.open(sDetailsFileName);
868     if(fout.good() == false)
869     {
870         fout.close();
871         return;
872     }
873     for (auto data : records)
874     {
875         fout << getDashString((uint32_t)data.first.length());
876         fout << data.first << std::endl;
877         fout << getDashString((uint32_t)data.first.length());
878         for (auto t : *data.second)
879         {
880             fout << t.time << std::endl;
881         }
882         fout << std::endl;
883     }
884 
885     fout.close();
886     return;
887 }
888 
printHeader(std::ofstream & fout)889 void PerfUtility::printHeader(std::ofstream& fout)
890 {
891     fout << "Summary: " << std::endl;
892     std::stringstream ss;
893     ss << "CPU Latency Tag,";
894     ss << "Hit Count,";
895     ss << "Average (ms),";
896     ss << "Minimum (ms),";
897     ss << "Maximum (ms)" << std::endl;
898     fout << ss.str();
899 }
900 
printBody(std::ofstream & fout)901 void PerfUtility::printBody(std::ofstream& fout)
902 {
903     for (const auto& data : records)
904     {
905         fout << formatPerfData(data.first, *data.second);
906     }
907 }
908 
formatPerfData(std::string tag,std::vector<Tick> & record)909 std::string PerfUtility::formatPerfData(std::string tag, std::vector<Tick>& record)
910 {
911     std::stringstream ss;
912     PerfInfo info = {};
913     getPerfInfo(record, &info);
914 
915     ss << tag;
916     ss << ",";
917     ss.precision(3);
918     ss.setf(std::ios::fixed, std::ios::floatfield);
919 
920     ss << info.count;
921     ss << ",";
922     ss << info.avg;
923     ss << ",";
924     ss << info.min;
925     ss << ",";
926     ss << info.max << std::endl;
927 
928     return ss.str();
929 }
930 
getPerfInfo(std::vector<Tick> & record,PerfInfo * info)931 void PerfUtility::getPerfInfo(std::vector<Tick>& record, PerfInfo* info)
932 {
933     if (record.size() <= 0)
934         return;
935 
936     info->count = (uint32_t)record.size();
937     double sum = 0, max = 0, min = 10000000.0;
938     for (auto t : record)
939     {
940         sum += t.time;
941         max = (max < t.time) ? t.time : max;
942         min = (min > t.time) ? t.time : min;
943     }
944     info->avg = sum / info->count;
945     info->max = max;
946     info->min = min;
947 }
948 
printFooter(std::ofstream & fout)949 void PerfUtility::printFooter(std::ofstream& fout)
950 {
951     fout << getDashString(80);
952 }
953 
getDashString(uint32_t num)954 std::string PerfUtility::getDashString(uint32_t num)
955 {
956     std::stringstream ss;
957     ss.width(num);
958     ss.fill('-');
959     ss << std::left << "" << std::endl;
960     return ss.str();
961 }