Table of Contents

Target Platform(s):
Wwise SDK 2019.2.2
AkPlatformFuncs.h
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  Version: <VERSION> Build: <BUILDNUMBER>
25  Copyright (c) <COPYRIGHTYEAR> Audiokinetic Inc.
26 *******************************************************************************/
27 
28 #pragma once
29 
30 #include <AK/Tools/Common/AkAssert.h>
31 #include <AK/SoundEngine/Common/AkTypes.h>
32 #include <android/log.h>
33 
34 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
35 #include <cpuid.h>
36 #endif
37 #include <time.h>
38 #include <stdlib.h>
39 
40 #define AK_THREAD_INIT_CODE(_threadProperties) syscall(__NR_sched_setaffinity, 0, sizeof(_threadProperties.dwAffinityMask), &_threadProperties.dwAffinityMask)
41 #define AK_SEC_TO_NANOSEC 1000000000ULL
42 
43 namespace AKPLATFORM
44 {
45  /// Platform Independent Helper
46  inline void PerformanceFrequency( AkInt64 * out_piFreq )
47  {
48  //Since Wall Clock is used, 1 NS is the frequency independent of the clock resolution
49  *out_piFreq = AK_SEC_TO_NANOSEC;
50  }
51 }
52 
53 #include <AK/Tools/POSIX/AkPlatformFuncs.h>
54 
55 #if (defined AK_LUMIN) && !(defined AK_OPTIMIZED)
56 #include <ml_logging.h>
57 #endif
58 
59 namespace AKPLATFORM
60 {
61  /// Output a debug message on the console (Ansi string)
62 #if (defined AK_OPTIMIZED)
63  inline void OutputDebugMsg( const char* ){}
64 #elif (defined AK_LUMIN)
65  inline void OutputDebugMsg( const char* in_pszMsg )
66  {
67  ML_LOG_TAG(Info, "AKDEBUG", "%s", in_pszMsg);
68  }
69 #else
70  inline void OutputDebugMsg( const char* in_pszMsg )
71  {
72  // To see output of this
73  // adb logcat ActivityManager:I YourApplication:D AKDEBUG:D *:S
74  __android_log_print(ANDROID_LOG_INFO, "AKDEBUG", "%s", in_pszMsg);
75  }
76 #endif
77 
78  // Time functions
79  // ------------------------------------------------------------------
80 
81  /// Platform Independent Helper
82  inline void PerformanceCounter( AkInt64 * out_piLastTime )
83  {
84  struct timespec clockNow;
85  clock_gettime(CLOCK_MONOTONIC, &clockNow);
86  //This give the wallclock time in NS
87  *out_piLastTime = clockNow.tv_sec*AK_SEC_TO_NANOSEC + clockNow.tv_nsec;
88  }
89 
90 
91  template<class destType, class srcType>
92  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 *) )
93  {
94  size_t i;
95  size_t lenToCopy = srcStrLen(in_pSrc);
96 
97  lenToCopy = (lenToCopy > in_MaxSize-1) ? in_MaxSize-1 : lenToCopy;
98  for(i = 0; i < lenToCopy; i++)
99  {
100  in_pdDest[i] = (destType) in_pSrc[i];
101  }
102  in_pdDest[lenToCopy] = (destType)0;
103 
104  return lenToCopy;
105  }
106 
107  #define CONVERT_UTF16_TO_CHAR( _astring_, _charstring_ ) \
108  _charstring_ = (char*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(char) ); \
109  AK_UTF16_TO_CHAR( _charstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 )
110 
111  #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
112  #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen )
113  #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)
114  #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen)
115 
116  /// Stack allocations.
117  #define AkAlloca( _size_ ) __builtin_alloca( _size_ )
118 
119  #if __BIGGEST_ALIGNMENT__ < AK_SIMD_ALIGNMENT
120  #define AkAllocaSIMD( _size_ ) __builtin_alloca_with_align( _size_, AK_SIMD_ALIGNMENT*8 )
121  #endif
122 
123  /// Platform Independent Helper
124  inline void AkCreateThread(
125  AkThreadRoutine pStartRoutine, // Thread routine.
126  void * pParams, // Routine params.
127  const AkThreadProperties & in_threadProperties, // Properties. NULL for default.
128  AkThread * out_pThread, // Returned thread handle.
129  const char * /*in_szThreadName*/ ) // Opt thread name.
130  {
131  AKASSERT( out_pThread != NULL );
132 
133  pthread_attr_t attr;
134 
135  // Create the attr
136  AKVERIFY(!pthread_attr_init(&attr));
137  // Set the stack size
138  AKVERIFY(!pthread_attr_setstacksize(&attr,in_threadProperties.uStackSize));
139 
140  AKVERIFY(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
141 
142  // Create the tread
143  int threadError = pthread_create( out_pThread, &attr, pStartRoutine, pParams);
144  AKASSERT( threadError == 0 );
145  AKVERIFY(!pthread_attr_destroy(&attr));
146 
147  if( threadError != 0 )
148  {
149  AkClearThread( out_pThread );
150  return;
151  }
152 
153  // ::CreateThread() return NULL if it fails.
154  if ( !*out_pThread )
155  {
156  AkClearThread( out_pThread );
157  return;
158  }
159 
160  // Try to set the thread policy
161  int sched_policy = in_threadProperties.uSchedPolicy;
162 
163  // Get the priority for the policy
164  int minPriority, maxPriority;
165  minPriority = sched_get_priority_min(sched_policy);
166  maxPriority = sched_get_priority_max(sched_policy);
167 
168  // Set the thread priority if valid
169  sched_param schedParam;
170  schedParam.sched_priority = in_threadProperties.nPriority;
171  AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority );
172 
173  //pthread_setschedparam WILL fail on Android Lollipop when used with SCHED_FIFO (the default). Not allowed anymore. (ignore the error code).
174  int err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
175  if (err != 0)
176  {
177  //Make sure the priority is well set, even if the policy could not.
178  sched_policy = SCHED_NORMAL;
179  minPriority = sched_get_priority_min(sched_policy);
180  maxPriority = sched_get_priority_max(sched_policy);
181  if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_ABOVE_NORMAL)
182  schedParam.sched_priority = maxPriority;
183  else if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_BELOW_NORMAL)
184  schedParam.sched_priority = minPriority;
185  else
186  schedParam.sched_priority = (maxPriority + minPriority) / 2;
187  err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam);
188  AKASSERT(err == 0);
189  }
190  }
191 
192 #if (defined(AK_CPU_X86_64) || defined(AK_CPU_X86))
193  // Once our minimum compiler version supports __get_cpuid_count, these asm blocks can be replaced
194  #if defined(__i386__) && defined(__PIC__)
195  // %ebx may be the PIC register.
196  #define __ak_cpuid_count(level, count, a, b, c, d) \
197  __asm__ ("xchg{l}\t{%%}ebx, %k1\n\t" \
198  "cpuid\n\t" \
199  "xchg{l}\t{%%}ebx, %k1\n\t" \
200  : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
201  : "0" (level), "2" (count))
202  #elif defined(__x86_64__) && defined(__PIC__)
203  // %rbx may be the PIC register.
204  #define __ak_cpuid_count(level, count, a, b, c, d) \
205  __asm__ ("xchg{q}\t{%%}rbx, %q1\n\t" \
206  "cpuid\n\t" \
207  "xchg{q}\t{%%}rbx, %q1\n\t" \
208  : "=a" (a), "=&r" (b), "=c" (c), "=d" (d) \
209  : "0" (level), "2" (count))
210  #else
211  #define __ak_cpuid_count(level, count, a, b, c, d) \
212  __asm__ ("cpuid\n\t" \
213  : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
214  : "0" (level), "2" (count))
215  #endif
216 
217  static __inline int __ak_get_cpuid_count(unsigned int __leaf,
218  unsigned int __subleaf,
219  unsigned int *__eax, unsigned int *__ebx,
220  unsigned int *__ecx, unsigned int *__edx)
221  {
222  unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
223 
224  if (__max_leaf == 0 || __max_leaf < __leaf)
225  return 0;
226 
227  __ak_cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
228  return 1;
229  }
230 
231  /// Support to fetch the CPUID for the platform. Only valid for X86 targets
232  /// \remark Note that IAkProcessorFeatures should be preferred to fetch this data
233  /// as it will have already translated the feature bits into AK-relevant enums
234  inline void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
235  {
236  __ak_get_cpuid_count( in_uLeafOpcode, in_uSubLeafOpcode,
237  &out_uCPUFeatures[0],
238  &out_uCPUFeatures[1],
239  &out_uCPUFeatures[2],
240  &out_uCPUFeatures[3]);
241  }
242 #endif
243 }
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:217
int nPriority
Thread priority.
Definition: AkPlatformFuncs.h:74
void OutputDebugMsg(const char *in_pszMsg)
Output a debug message on the console (Ansi string)
Definition: AkPlatformFuncs.h:65
void CPUID(AkUInt32 in_uLeafOpcode, AkUInt32 in_uSubLeafOpcode, unsigned int out_uCPUFeatures[4])
Definition: AkPlatformFuncs.h:234
void AkCreateThread(AkThreadRoutine pStartRoutine, void *pParams, const AkThreadProperties &in_threadProperties, AkThread *out_pThread, const char *)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:124
void PerformanceCounter(AkInt64 *out_piLastTime)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:82
AkForceInline void AkClearThread(AkThread *in_pThread)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:221
size_t uStackSize
Thread stack size.
Definition: AkPlatformFuncs.h:76
void PerformanceFrequency(AkInt64 *out_piFreq)
Platform Independent Helper.
Definition: AkPlatformFuncs.h:46
int uSchedPolicy
Thread scheduling policy.
Definition: AkPlatformFuncs.h:77
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:92