Version
menu_open
link
Target Platform(s):
Wwise SDK 2022.1.4
AkPlatformFuncs.h
Go to the documentation of this file.
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2023 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 #pragma once
28 
31 #include <android/log.h>
32 
33 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
34 #include <cpuid.h>
35 #endif
36 #include <time.h>
37 #include <stdlib.h>
38 
39 #define AK_THREAD_INIT_CODE(_threadProperties) syscall(__NR_sched_setaffinity, 0, sizeof(_threadProperties.dwAffinityMask), &_threadProperties.dwAffinityMask)
40 #define AK_SEC_TO_NANOSEC 1000000000ULL
41 
42 namespace AKPLATFORM
43 {
44  /// Platform Independent Helper
45  inline void PerformanceFrequency( AkInt64 * out_piFreq )
46  {
47  //Since Wall Clock is used, 1 NS is the frequency independent of the clock resolution
48  *out_piFreq = AK_SEC_TO_NANOSEC;
49  }
50 }
51 
52 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
53 
54 #if (defined AK_LUMIN) && !(defined AK_OPTIMIZED)
55 #include <ml_logging.h>
56 #endif
57 
58 /// Stack allocations.
59 #define AkAlloca( _size_ ) __builtin_alloca( _size_ )
60 
61 namespace AKPLATFORM
62 {
63  /// Output a debug message on the console (Ansi string)
64 
65 #if defined(AK_OPTIMIZED)
66  inline void OutputDebugMsg( const char* ){}
67 
68  template <int MaxSize = 0> // Unused
69  inline void OutputDebugMsgV( const char* in_pszFmt, ... ) {}
70 #elif defined(AK_LUMIN)
71  inline void OutputDebugMsg( const char* in_pszMsg )
72  {
73  // To see output of this (mldb on lumin)
74  // mldb logcat ActivityManager:I YourApplication:D AKDEBUG:D *:S
75  ML_LOG_TAG(Info, "AKDEBUG", "%s", in_pszMsg);
76  }
77 
78  /// Output a debug message on the console (variadic function).
79  template <int MaxSize = 256>
80  inline void OutputDebugMsgV( const char* in_pszFmt, ... )
81  {
82  // magic leap doesn't have a log that takes a va_list
83 
84  int size = 0;
85  {
86  // Try with a reasonable guess first
87  char msg[MaxSize];
88  msg[MaxSize - 1] = '\0';
89 
90  va_list args;
91  va_start(args, in_pszFmt);
92  size = vsnprintf(msg, MaxSize, in_pszFmt, args);
93  va_end(args);
94 
95  // If it was enough, print to debug log
96  if (0 <= size && size <= MaxSize)
97  {
98  ML_LOG_TAG(Info, "AKDEBUG", in_pszFmt, args);
99  return;
100  }
101  }
102 
103  // Else, we need more memory to prevent truncation
104  {
105  // size + 1 more char for the last '\0'
106  size++;
107 
108  char* msg = (char*)AkAlloca((size) * sizeof(char));
109  msg[size - 1] = '\0';
110 
111  va_list args;
112  va_start(args, in_pszFmt);
113  vsnprintf(msg, size, in_pszFmt, args);
114  va_end(args);
115 
116  ML_LOG_TAG(Info, "AKDEBUG", in_pszFmt, args);
117  }
118  }
119 #else // AK_ANDROID
120  inline void OutputDebugMsg( const char* in_pszMsg )
121  {
122  // To see output of this
123  // adb logcat ActivityManager:I YourApplication:D AKDEBUG:D *:S
124  __android_log_print(ANDROID_LOG_INFO, "AKDEBUG", "%s", in_pszMsg);
125  }
126 
127  /// Output a debug message on the console (variadic function).
128  template <int MaxSize = 0> // Unused
129  inline void OutputDebugMsgV( const char* in_pszFmt, ...)
130  {
131  va_list args;
132  va_start(args, in_pszFmt);
133  __android_log_vprint(ANDROID_LOG_INFO, "AKDEBUG", in_pszFmt, args);
134  va_end(args);
135  }
136 #endif
137 
138  // Time functions
139  // ------------------------------------------------------------------
140 
141  /// Platform Independent Helper
142  inline void PerformanceCounter( AkInt64 * out_piLastTime )
143  {
144  struct timespec clockNow;
145  clock_gettime(CLOCK_MONOTONIC, &clockNow);
146  //This give the wallclock time in NS
147  *out_piLastTime = clockNow.tv_sec*AK_SEC_TO_NANOSEC + clockNow.tv_nsec;
148  }
149 
150 
151  template<class destType, class srcType>
152  inline size_t AkSimpleConvertString( destType* in_pdDest, const srcType* in_pSrc, size_t in_MaxSize, size_t destStrLen(const destType *), size_t srcStrLen(const srcType *) )
153  {
154  size_t i;
155  size_t lenToCopy = srcStrLen(in_pSrc);
156 
157  lenToCopy = (lenToCopy > in_MaxSize-1) ? in_MaxSize-1 : lenToCopy;
158  for(i = 0; i < lenToCopy; i++)
159  {
160  in_pdDest[i] = (destType) in_pSrc[i];
161  }
162  in_pdDest[lenToCopy] = (destType)0;
163 
164  return lenToCopy;
165  }
166 
167  #define CONVERT_UTF16_TO_CHAR( _astring_, _charstring_ ) \
168  _charstring_ = (char*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(char) ); \
169  AK_UTF16_TO_CHAR( _charstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 )
170 
171  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, strlen )
172  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
173  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
174  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)
175  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)
176 
177  #if __BIGGEST_ALIGNMENT__ < AK_SIMD_ALIGNMENT
178  #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, AK_SIMD_ALIGNMENT*8 )
179  #endif
180 
181  /// Platform Independent Helper
182  inline void AkCreateThread(
183  AkThreadRoutine pStartRoutine, // Thread routine.
184  void * pParams, // Routine params.
185  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
186  AkThread * out_pThread, // Returned thread handle.
187  const char * /*in_szThreadName*/ ) // Opt thread name.
188  {
189  AKASSERT( out_pThread != NULL );
190 
191  pthread_attr_t attr;
192 
193  // Create the attr
194  AKVERIFY(!pthread_attr_init(&attr));
195  // Set the stack size
196  AKVERIFY(!pthread_attr_setstacksize(&attr,in_threadProperties.uStackSize));
197 
198  AKVERIFY(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
199 
200  // Create the tread
201  int threadError = pthread_create( out_pThread, &attr, pStartRoutine, pParams);
202  AKASSERT( threadError == 0 );
203  AKVERIFY(!pthread_attr_destroy(&attr));
204 
205  if( threadError != 0 )
206  {
207  AkClearThread( out_pThread );
208  return;
209  }
210 
211  // ::CreateThread() return NULL if it fails.
212  if ( !*out_pThread )
213  {
214  AkClearThread( out_pThread );
215  return;
216  }
217 
218  // Try to set the thread policy
219  int sched_policy = in_threadProperties.uSchedPolicy;
220 
221  // Get the priority for the policy
222  int minPriority, maxPriority;
223  minPriority = sched_get_priority_min(sched_policy);
224  maxPriority = sched_get_priority_max(sched_policy);
225 
226  // Set the thread priority if valid
227  sched_param schedParam;
228  schedParam.sched_priority = in_threadProperties.nPriority;
229  AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );
230 
231  //pthread_setschedparam WILL fail on Android Lollipop when used with SCHED_FIFO (the default). Not allowed anymore. (ignore the error code).
232  int err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
233  if (err != 0)
234  {
235  //Make sure the priority is well set, even if the policy could not.
236  sched_policy = SCHED_NORMAL;
237  minPriority = sched_get_priority_min(sched_policy);
238  maxPriority = sched_get_priority_max(sched_policy);
239  if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_ABOVE_NORMAL)
240  schedParam.sched_priority = maxPriority;
241  else if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_BELOW_NORMAL)
242  schedParam.sched_priority = minPriority;
243  else
244  schedParam.sched_priority = (maxPriority + minPriority) / 2;
245  err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
246  AKASSERT(err == 0);
247  }
248  }
249 
250  #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
251  #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
252 
253 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
254  // Once our minimum compiler version supports __get_cpuid_count, these asm blocks can be replaced
255  #if defined(__i386__) && defined(__PIC__)
256  // %ebx may be the PIC register.
257  #define __ak_cpuid_count(level, count, a, b, c, d) \
258  __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \
259  "cpuid\n\t" \
260  "xchg{l}\t{%%}ebx, %k1\n\t" \
261  : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
262  : "0" (level), "2" (count))
263  #elif defined(__x86_64__) && defined(__PIC__)
264  // %rbx may be the PIC register.
265  #define __ak_cpuid_count(level, count, a, b, c, d) \
266  __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \
267  "cpuid\n\t" \
268  "xchg{q}\t{%%}rbx, %q1\n\t" \
269  : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
270  : "0" (level), "2" (count))
271  #else
272  #define __ak_cpuid_count(level, count, a, b, c, d) \
273  __asm__ ("cpuid\n\t" \
274  : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
275  : "0" (level), "2" (count))
276  #endif
277 
278  static __inline int __ak_get_cpuid_count(unsigned int __leaf,
279  unsigned int __subleaf,
280  unsigned int *__eax, unsigned int *__ebx,
281  unsigned int *__ecx, unsigned int *__edx)
282  {
283  unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
284 
285  if (__max_leaf == 0 || __max_leaf < __leaf)
286  return 0;
287 
288  __ak_cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
289  return 1;
290  }
291 
292  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
293  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
294  /// as it will have already translated the feature bits into AK-relevant enums
295  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
296  {
297  __ak_get_cpuid_count( in_uLeafOpcode, in_uSubLeafOpcode,
298  &out_uCPUFeatures[0],
299  &out_uCPUFeatures[1],
300  &out_uCPUFeatures[2],
301  &out_uCPUFeatures[3]);
302  }
303 #endif
304 }
static __inline int __ak_get_cpuid_count(unsigned int __leaf, unsigned int __subleaf, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx)
Definition: AkPlatformFuncs.h:278
int nPriority
Thread priority.
Definition: AkPlatformFuncs.h:48
Platform-dependent helpers.
Definition: AkPlatformFuncs.h:156
#define __ak_cpuid_count(level, count, a, b, c, d)
Definition: AkPlatformFuncs.h:272
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
Definition: AkPlatformFuncs.h:120
void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
Definition: AkPlatformFuncs.h:295
#define NULL
Definition: AkTypes.h:46
#define AK_THREAD_PRIORITY_ABOVE_NORMAL
Definition: AkPlatformFuncs.h:78
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:182
void OutputDebugMsgV(const char *in_pszFmt,...)
Output a debug message on the console (variadic function).
Definition: AkPlatformFuncs.h:129
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:142
nn::os::ThreadFunction AkThreadRoutine
Thread routine.
Definition: AkTypes.h:85
#define AKASSERT(Condition)
Definition: AkAssert.h:67
#define AKVERIFY(x)
Definition: AkAssert.h:69
#define AkAlloca(_size_)
Stack allocations.
Definition: AkPlatformFuncs.h:59
#define AK_SEC_TO_NANOSEC
Definition: AkPlatformFuncs.h:40
AkForceInline void AkClearThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:283
int64_t AkInt64
Signed 64-bit integer.
Definition: AkNumeralTypes.h:44
size_t uStackSize
Thread stack size.
Definition: AkPlatformFuncs.h:50
void PerformanceFrequency(AkInt64 *out_piFreq)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:45
int uSchedPolicy
Thread scheduling policy.
Definition: AkPlatformFuncs.h:51
uint32_t AkUInt32
Unsigned 32-bit integer.
Definition: AkNumeralTypes.h:38
#define AK_THREAD_PRIORITY_BELOW_NORMAL
Definition: AkPlatformFuncs.h:79
size_t AkSimpleConvertString(destType *in_pdDest, const srcType *in_pSrc, size_t in_MaxSize, size_t destStrLen(const destType *), size_t srcStrLen(const srcType *))
Definition: AkPlatformFuncs.h:152
Definition: AkTypes.h:90

Was this page helpful?

Need Support?

Questions? Problems? Need more info? Contact us, and we can help!

Visit our Support page

Tell us about your project. We're here to help.

Register your project and we'll help you get started with no strings attached!

Get started with Wwise