Version
menu_open
link
Target Platform(s):
Wwise SDK 2023.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) 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 /// Stack allocations.
64 #define AkAlloca( _size_ ) __builtin_alloca( _size_ )
65 
66 namespace AKPLATFORM
67 {
68  /// Output a debug message on the console (Ansi string)
69 
70 #if defined(AK_OPTIMIZED)
71  inline void OutputDebugMsg( const char* ){}
72 
73  template <int MaxSize = 0> // Unused
74  inline void OutputDebugMsgV( const char* in_pszFmt, ... ) {}
75 #else // AK_ANDROID
76  inline void OutputDebugMsg( const char* in_pszMsg )
77  {
78  // To see output of this
79  // adb logcat ActivityManager:I YourApplication:D AKDEBUG:D *:S
80  __android_log_print(ANDROID_LOG_INFO, "AKDEBUG", "%s", in_pszMsg);
81  }
82 
83  /// Output a debug message on the console (variadic function).
84  template <int MaxSize = 0> // Unused
85  inline void OutputDebugMsgV( const char* in_pszFmt, ...)
86  {
87  va_list args;
88  va_start(args, in_pszFmt);
89  __android_log_vprint(ANDROID_LOG_INFO, "AKDEBUG", in_pszFmt, args);
90  va_end(args);
91  }
92 #endif
93 
94  template<class destType, class srcType>
95  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 *) )
96  {
97  size_t i;
98  size_t lenToCopy = srcStrLen(in_pSrc);
99 
100  lenToCopy = (lenToCopy > in_MaxSize-1) ? in_MaxSize-1 : lenToCopy;
101  for(i = 0; i < lenToCopy; i++)
102  {
103  in_pdDest[i] = (destType) in_pSrc[i];
104  }
105  in_pdDest[lenToCopy] = (destType)0;
106 
107  return lenToCopy;
108  }
109 
110  #define CONVERT_UTF16_TO_CHAR( _astring_, _charstring_ ) \
111  _charstring_ = (char*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(char) ); \
112  AK_UTF16_TO_CHAR( _charstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 )
113 
114  #define AK_UTF8_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, strlen )
115  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
116  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
117  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)
118  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)
119 
120  #if __BIGGEST_ALIGNMENT__ < AK_SIMD_ALIGNMENT
121  #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, AK_SIMD_ALIGNMENT*8 )
122  #endif
123 
124  /// Platform Independent Helper
125  inline void AkCreateThread(
126  AkThreadRoutine pStartRoutine, // Thread routine.
127  void * pParams, // Routine params.
128  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
129  AkThread * out_pThread, // Returned thread handle.
130  const char * /*in_szThreadName*/ ) // Opt thread name.
131  {
132  AKASSERT( out_pThread != NULL );
133 
134  pthread_attr_t attr;
135 
136  // Create the attr
137  AKVERIFY(!pthread_attr_init(&attr));
138  // Set the stack size
139  AKVERIFY(!pthread_attr_setstacksize(&attr,in_threadProperties.uStackSize));
140 
141  AKVERIFY(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
142 
143  // Create the tread
144  int threadError = pthread_create( out_pThread, &attr, pStartRoutine, pParams);
145  AKASSERT( threadError == 0 );
146  AKVERIFY(!pthread_attr_destroy(&attr));
147 
148  if( threadError != 0 )
149  {
150  AkClearThread( out_pThread );
151  return;
152  }
153 
154  // ::CreateThread() return NULL if it fails.
155  if ( !*out_pThread )
156  {
157  AkClearThread( out_pThread );
158  return;
159  }
160 
161  // Try to set the thread policy
162  int sched_policy = in_threadProperties.uSchedPolicy;
163 
164  // Get the priority for the policy
165  int minPriority, maxPriority;
166  minPriority = sched_get_priority_min(sched_policy);
167  maxPriority = sched_get_priority_max(sched_policy);
168 
169  // Set the thread priority if valid
170  sched_param schedParam;
171  schedParam.sched_priority = in_threadProperties.nPriority;
172  AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );
173 
174  //pthread_setschedparam WILL fail on Android Lollipop when used with SCHED_FIFO (the default). Not allowed anymore. (ignore the error code).
175  int err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
176  if (err != 0)
177  {
178  //Make sure the priority is well set, even if the policy could not.
179  sched_policy = SCHED_NORMAL;
180  minPriority = sched_get_priority_min(sched_policy);
181  maxPriority = sched_get_priority_max(sched_policy);
182  if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_ABOVE_NORMAL)
183  schedParam.sched_priority = maxPriority;
184  else if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_BELOW_NORMAL)
185  schedParam.sched_priority = minPriority;
186  else
187  schedParam.sched_priority = (maxPriority + minPriority) / 2;
188  err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
189  AKASSERT(err == 0);
190  }
191  }
192 
193  #define AK_FILEHANDLE_TO_UINTPTR(_h) ((AkUIntPtr)_h)
194  #define AK_SET_FILEHANDLE_TO_UINTPTR(_h,_u) _h = (AkFileHandle)_u
195 
196 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
197  // Once our minimum compiler version supports __get_cpuid_count, these asm blocks can be replaced
198  #if defined(__i386__) && defined(__PIC__)
199  // %ebx may be the PIC register.
200  #define __ak_cpuid_count(level, count, a, b, c, d) \
201  __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \
202  "cpuid\n\t" \
203  "xchg{l}\t{%%}ebx, %k1\n\t" \
204  : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
205  : "0" (level), "2" (count))
206  #elif defined(__x86_64__) && defined(__PIC__)
207  // %rbx may be the PIC register.
208  #define __ak_cpuid_count(level, count, a, b, c, d) \
209  __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \
210  "cpuid\n\t" \
211  "xchg{q}\t{%%}rbx, %q1\n\t" \
212  : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
213  : "0" (level), "2" (count))
214  #else
215  #define __ak_cpuid_count(level, count, a, b, c, d) \
216  __asm__ ("cpuid\n\t" \
217  : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
218  : "0" (level), "2" (count))
219  #endif
220 
221  static __inline int __ak_get_cpuid_count(unsigned int __leaf,
222  unsigned int __subleaf,
223  unsigned int *__eax, unsigned int *__ebx,
224  unsigned int *__ecx, unsigned int *__edx)
225  {
226  unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
227 
228  if (__max_leaf == 0 || __max_leaf < __leaf)
229  return 0;
230 
231  __ak_cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
232  return 1;
233  }
234 
235  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
236  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
237  /// as it will have already translated the feature bits into AK-relevant enums
238  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
239  {
240  __ak_get_cpuid_count( in_uLeafOpcode, in_uSubLeafOpcode,
241  &out_uCPUFeatures[0],
242  &out_uCPUFeatures[1],
243  &out_uCPUFeatures[2],
244  &out_uCPUFeatures[3]);
245  }
246 #endif
247 }
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.
Definition: AkBitFuncs.h:43
#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:90
#define AKASSERT(Condition)
Definition: AkAssert.h:67
#define AKVERIFY(x)
Definition: AkAssert.h:69
#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