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

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