目录

include/AK/Tools/Android/AkPlatformFuncs.h

Go to the documentation of this file.
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 }