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