00001 00002 // 00003 // AkPlatformFuncs.h 00004 // 00005 // Audiokinetic platform-dependent functions definition. 00006 // 00007 // Copyright (c) 2006 Audiokinetic Inc. / All Rights Reserved 00008 // 00010 00011 #pragma once 00012 00013 #include <AK/Tools/Common/AkAssert.h> 00014 #include <AK/SoundEngine/Common/AkTypes.h> 00015 #include <android/log.h> 00016 00017 #include <time.h> 00018 #include <stdlib.h> 00019 00020 #define AK_THREAD_INIT_CODE(_threadProperties) syscall(__NR_sched_setaffinity, 0, sizeof(_threadProperties.dwAffinityMask), &_threadProperties.dwAffinityMask) 00021 00022 00023 namespace AKPLATFORM 00024 { 00026 inline void PerformanceFrequency( AkInt64 * out_piFreq ) 00027 { 00028 // TO DO ANDROID ... is there something better 00029 *out_piFreq = CLOCKS_PER_SEC; 00030 } 00031 } 00032 00033 #include <AK/Tools/POSIX/AkPlatformFuncs.h> 00034 00035 namespace AKPLATFORM 00036 { 00037 00038 #ifndef AK_OPTIMIZED 00039 00040 inline void OutputDebugMsg( const char* in_pszMsg ) 00041 { 00042 // To see output of this 00043 // adb logcat ActivityManager:I YourApplication:D AKDEBUG:D *:S 00044 __android_log_print(ANDROID_LOG_INFO, "AKDEBUG", "%s", in_pszMsg); 00045 } 00046 #else 00047 inline void OutputDebugMsg( const char* ){} 00048 #endif 00049 // Atomic Operations 00050 // ------------------------------------------------------------------ 00051 00053 inline AkInt32 AkInterlockedIncrement( AkInt32 * pValue ) 00054 { 00055 return __atomic_add_fetch(pValue,1, __ATOMIC_SEQ_CST); 00056 } 00057 00059 inline AkInt32 AkInterlockedDecrement( AkInt32 * pValue ) 00060 { 00061 return __atomic_sub_fetch(pValue,1, __ATOMIC_SEQ_CST); 00062 } 00063 00064 inline bool AkInterlockedCompareExchange( volatile AkInt32* io_pDest, AkInt32 in_newValue, AkInt32 in_expectedOldVal ) 00065 { 00066 return __atomic_compare_exchange(io_pDest, &in_expectedOldVal, &in_newValue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 00067 } 00068 00069 inline bool AkInterlockedCompareExchange( volatile AkInt64* io_pDest, AkInt64 in_newValue, AkInt64 in_expectedOldVal ) 00070 { 00071 return __atomic_compare_exchange(io_pDest, &in_expectedOldVal, &in_newValue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 00072 } 00073 00074 inline void AkMemoryBarrier() 00075 { 00076 __atomic_thread_fence(__ATOMIC_SEQ_CST); 00077 /* 00078 #ifdef AK_CPU_ARM 00079 __asm("DMB ST"); //Wait for stores to complete. 00080 #elif AK_CPU_X86 00081 __asm("mfence"); 00082 #endif*/ 00083 } 00084 00085 // Time functions 00086 // ------------------------------------------------------------------ 00087 00089 inline void PerformanceCounter( AkInt64 * out_piLastTime ) 00090 { 00091 *out_piLastTime = clock(); 00092 } 00093 00094 00095 template<class destType, class srcType> 00096 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 *) ) 00097 { 00098 size_t i; 00099 size_t lenToCopy = srcStrLen(in_pSrc); 00100 00101 lenToCopy = (lenToCopy > in_MaxSize-1) ? in_MaxSize-1 : lenToCopy; 00102 for(i = 0; i < lenToCopy; i++) 00103 { 00104 in_pdDest[i] = (destType) in_pSrc[i]; 00105 } 00106 in_pdDest[lenToCopy] = (destType)0; 00107 00108 return lenToCopy; 00109 } 00110 00111 #define CONVERT_UTF16_TO_CHAR( _astring_, _charstring_ ) \ 00112 _charstring_ = (char*)AkAlloca( (1 + AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)) * sizeof(char) ); \ 00113 AK_UTF16_TO_CHAR( _charstring_, (const AkUtf16*)_astring_, AKPLATFORM::AkUtf16StrLen((const AkUtf16*)_astring_)+1 ) 00114 00115 #define AK_UTF16_TO_OSCHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen ) 00116 #define AK_UTF16_TO_CHAR( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, strlen, AKPLATFORM::AkUtf16StrLen ) 00117 #define AK_CHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen) 00118 #define AK_OSCHAR_TO_UTF16( in_pdDest, in_pSrc, in_MaxSize ) AKPLATFORM::AkSimpleConvertString( in_pdDest, in_pSrc, in_MaxSize, AKPLATFORM::AkUtf16StrLen, strlen) 00119 00121 #define AkAlloca( _size_ ) __builtin_alloca( _size_ ) 00122 00124 inline void AkCreateThread( 00125 AkThreadRoutine pStartRoutine, // Thread routine. 00126 void * pParams, // Routine params. 00127 const AkThreadProperties & in_threadProperties, // Properties. NULL for default. 00128 AkThread * out_pThread, // Returned thread handle. 00129 const char * /*in_szThreadName*/ ) // Opt thread name. 00130 { 00131 AKASSERT( out_pThread != NULL ); 00132 00133 pthread_attr_t attr; 00134 00135 // Create the attr 00136 AKVERIFY(!pthread_attr_init(&attr)); 00137 // Set the stack size 00138 AKVERIFY(!pthread_attr_setstacksize(&attr,in_threadProperties.uStackSize)); 00139 00140 AKVERIFY(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); 00141 00142 // Create the tread 00143 int threadError = pthread_create( out_pThread, &attr, pStartRoutine, pParams); 00144 AKASSERT( threadError == 0 ); 00145 AKVERIFY(!pthread_attr_destroy(&attr)); 00146 00147 if( threadError != 0 ) 00148 { 00149 AkClearThread( out_pThread ); 00150 return; 00151 } 00152 00153 // ::CreateThread() return NULL if it fails. 00154 if ( !*out_pThread ) 00155 { 00156 AkClearThread( out_pThread ); 00157 return; 00158 } 00159 00160 // Try to set the thread policy 00161 int sched_policy = in_threadProperties.uSchedPolicy; 00162 00163 // Get the priority for the policy 00164 int minPriority, maxPriority; 00165 minPriority = sched_get_priority_min(sched_policy); 00166 maxPriority = sched_get_priority_max(sched_policy); 00167 00168 // Set the thread priority if valid 00169 sched_param schedParam; 00170 schedParam.sched_priority = in_threadProperties.nPriority; 00171 AKASSERT( in_threadProperties.nPriority >= minPriority && in_threadProperties.nPriority <= maxPriority ); 00172 00173 //pthread_setschedparam WILL fail on Android Lollipop when used with SCHED_FIFO (the default). Not allowed anymore. (ignore the error code). 00174 int err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam); 00175 if (err != 0) 00176 { 00177 //Make sure the priority is well set, even if the policy could not. 00178 sched_policy = SCHED_NORMAL; 00179 minPriority = sched_get_priority_min(sched_policy); 00180 maxPriority = sched_get_priority_max(sched_policy); 00181 if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_ABOVE_NORMAL) 00182 schedParam.sched_priority = maxPriority; 00183 else if (in_threadProperties.nPriority == AK_THREAD_PRIORITY_BELOW_NORMAL) 00184 schedParam.sched_priority = minPriority; 00185 else 00186 schedParam.sched_priority = (maxPriority + minPriority) / 2; 00187 err = pthread_setschedparam(*out_pThread, sched_policy, &schedParam); 00188 AKASSERT(err == 0); 00189 } 00190 } 00191 }
Questions? Problems? Need more info? Contact us, and we can help!
Visit our Support pageRegister your project and we'll help you get started with no strings attached!
Get started with Wwise