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 }