From a6ec70fe9096529590ef806cf4f7b70b4cb19371 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 01:54:55 +0530 Subject: [PATCH 1/7] Audio Processor now uses atomics rather than mutex --- Core/HLE/__sceAudio.cpp | 51 +++++++++++++++++++++++++++++++++++++---- Core/HLE/__sceAudio.h | 4 +++- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 10f05c7519..3faec635ae 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -29,8 +29,9 @@ #include "FixedSizeQueue.h" #include "Common/Thread.h" + // Should be used to lock anything related to the outAudioQueue. -recursive_mutex section; +std::atomic audioQueueLock; int eventAudioUpdate = -1; int eventHostAudioUpdate = -1; @@ -55,6 +56,10 @@ static int chanQueueMinSizeFactor; // is bad mojo. FixedSizeQueue outAudioQueue; + +bool __gainAudioQueueLock(); + + static inline s16 clamp_s16(int i) { if (i > 32767) return 32767; @@ -108,6 +113,8 @@ void __AudioInit() { mixBuffer = new s32[hwBlockSize * 2]; memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32)); + + audioQueueLock.store(false); } void __AudioDoState(PointerWrap &p) { @@ -123,8 +130,15 @@ void __AudioDoState(PointerWrap &p) { p.Do(mixFrequency); { - lock_guard guard(section); + if(!__gainAudioQueueLock()){ + return; + } + outAudioQueue.DoState(p); + + //release the atomic lock + audioQueueLock.store(false); + } int chanCount = ARRAY_SIZE(chans); @@ -322,11 +336,18 @@ void __AudioUpdate() { } if (g_Config.bEnableSound) { - lock_guard guard(section); + + //looks like the heavy lifting is done here. + //we have to optimize this some more. + if(!__gainAudioQueueLock()){ + return; + } + if (outAudioQueue.room() >= hwBlockSize * 2) { s16 *buf1 = 0, *buf2 = 0; size_t sz1, sz2; outAudioQueue.pushPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2); + for (size_t s = 0; s < sz1; s++) buf1[s] = clamp_s16(mixBuffer[s]); if (buf2) { @@ -337,6 +358,9 @@ void __AudioUpdate() { // This happens quite a lot. There's still something slightly off // about the amount of audio we produce. } + + //release the atomic lock + audioQueueLock.store(false); } } @@ -352,12 +376,21 @@ int __AudioMix(short *outstereo, int numFrames) const s16 *buf1 = 0, *buf2 = 0; size_t sz1, sz2; { - lock_guard guard(section); + + if(!__gainAudioQueueLock()){ + return numFrames; + } + + outAudioQueue.popPointers(numFrames * 2, &buf1, &sz1, &buf2, &sz2); + memcpy(outstereo, buf1, sz1 * sizeof(s16)); if (buf2) { memcpy(outstereo + sz1, buf2, sz2 * sizeof(s16)); } + + //release the atomic lock + audioQueueLock.store(false); } int remains = (int)(numFrames * 2 - sz1 - sz2); @@ -370,3 +403,13 @@ int __AudioMix(short *outstereo, int numFrames) } return underrun >= 0 ? underrun : numFrames; } + + +bool __gainAudioQueueLock(){ + if(audioQueueLock.load(std::memory_order::memory_order_relaxed) == true){ + return false; + } + + audioQueueLock.store(true, std::memory_order::memory_order_relaxed ); + return true; +}; diff --git a/Core/HLE/__sceAudio.h b/Core/HLE/__sceAudio.h index 403c2f961f..3178b51f5e 100644 --- a/Core/HLE/__sceAudio.h +++ b/Core/HLE/__sceAudio.h @@ -16,8 +16,10 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once - #include "sceAudio.h" +#include + + // Easy interface for sceAudio to write to, to keep the complexity in check. From 43a0d5f60f667a08e25355e124536f68ac4205fd Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 11:01:21 +0530 Subject: [PATCH 2/7] changed the gitignore and android/project files --- .gitignore | 3 +++ android/.classpath | 18 +++++++++--------- android/ab.sh | 2 +- android/project.properties | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index f9dc576d5e..0db7a7d37b 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,6 @@ libat3plusdecoder.dylib libat3plusdecoder.so at3plusdecoder.dll at3plusdecoder64.dll + + +android/lint.xml diff --git a/android/.classpath b/android/.classpath index 26bdfa6eb5..51769745b2 100644 --- a/android/.classpath +++ b/android/.classpath @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/android/ab.sh b/android/ab.sh index 98dd7a71bf..1443abf761 100755 --- a/android/ab.sh +++ b/android/ab.sh @@ -1,3 +1,3 @@ cp -r ../flash0 assets cp -r ../lang assets -NDK_MODULE_PATH=..:../native/ext $NDK/ndk-build -j3 TARGET_PLATFORM=android-9 $* +NDK_MODULE_PATH=..:../native/ext ndk-build -j3 TARGET_PLATFORM=android-9 $* diff --git a/android/project.properties b/android/project.properties index babca9a8c9..84b11fd245 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-10 +target=android-18 android.library.reference.1=../native/android From a151b5beb63d6520109359530a19baf23cf88071 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 11:01:59 +0530 Subject: [PATCH 3/7] using PPSSPP's locks --- Core/HLE/__sceAudio.cpp | 26 ++++++++++++++++---------- Core/HLE/__sceAudio.h | 2 -- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 3faec635ae..fb0769f3b8 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -28,10 +28,11 @@ #include "ChunkFile.h" #include "FixedSizeQueue.h" #include "Common/Thread.h" - +#include "Common/Atomics.h" // Should be used to lock anything related to the outAudioQueue. -std::atomic audioQueueLock; +//atomic locks are used on the lock. TODO: make this lock-free +volatile u32 audioQueueLocked; int eventAudioUpdate = -1; int eventHostAudioUpdate = -1; @@ -58,7 +59,7 @@ FixedSizeQueue outAudioQueue; bool __gainAudioQueueLock(); - +void __releaseAcquiredLock(); static inline s16 clamp_s16(int i) { if (i > 32767) @@ -114,7 +115,8 @@ void __AudioInit() { mixBuffer = new s32[hwBlockSize * 2]; memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32)); - audioQueueLock.store(false); + //set the lock to false initially + Common::AtomicStore(audioQueueLocked, 0); } void __AudioDoState(PointerWrap &p) { @@ -137,7 +139,7 @@ void __AudioDoState(PointerWrap &p) { outAudioQueue.DoState(p); //release the atomic lock - audioQueueLock.store(false); + __releaseAcquiredLock(); } @@ -360,7 +362,7 @@ void __AudioUpdate() { } //release the atomic lock - audioQueueLock.store(false); + __releaseAcquiredLock(); } } @@ -390,7 +392,7 @@ int __AudioMix(short *outstereo, int numFrames) } //release the atomic lock - audioQueueLock.store(false); + __releaseAcquiredLock(); } int remains = (int)(numFrames * 2 - sz1 - sz2); @@ -405,11 +407,15 @@ int __AudioMix(short *outstereo, int numFrames) } -bool __gainAudioQueueLock(){ - if(audioQueueLock.load(std::memory_order::memory_order_relaxed) == true){ +inline bool __gainAudioQueueLock(){ + if(Common::AtomicLoad(audioQueueLocked) == 1){ return false; } - audioQueueLock.store(true, std::memory_order::memory_order_relaxed ); + Common::AtomicStore(audioQueueLocked, 1); return true; }; + +inline void __releaseAcquiredLock(){ + Common::AtomicStore(audioQueueLocked, 0); +} diff --git a/Core/HLE/__sceAudio.h b/Core/HLE/__sceAudio.h index 3178b51f5e..e338557683 100644 --- a/Core/HLE/__sceAudio.h +++ b/Core/HLE/__sceAudio.h @@ -17,8 +17,6 @@ #pragma once #include "sceAudio.h" -#include - // Easy interface for sceAudio to write to, to keep the complexity in check. From da66cb55f4fa91137b186e6ad9faaa98beff5f33 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 11:11:33 +0530 Subject: [PATCH 4/7] Revert "changed the gitignore and android/project files" This was to be done on a separate branch. Reverting change. This reverts commit 43a0d5f60f667a08e25355e124536f68ac4205fd. --- .gitignore | 3 --- android/.classpath | 18 +++++++++--------- android/ab.sh | 2 +- android/project.properties | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 0db7a7d37b..f9dc576d5e 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,3 @@ libat3plusdecoder.dylib libat3plusdecoder.so at3plusdecoder.dll at3plusdecoder64.dll - - -android/lint.xml diff --git a/android/.classpath b/android/.classpath index 51769745b2..26bdfa6eb5 100644 --- a/android/.classpath +++ b/android/.classpath @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/android/ab.sh b/android/ab.sh index 1443abf761..98dd7a71bf 100755 --- a/android/ab.sh +++ b/android/ab.sh @@ -1,3 +1,3 @@ cp -r ../flash0 assets cp -r ../lang assets -NDK_MODULE_PATH=..:../native/ext ndk-build -j3 TARGET_PLATFORM=android-9 $* +NDK_MODULE_PATH=..:../native/ext $NDK/ndk-build -j3 TARGET_PLATFORM=android-9 $* diff --git a/android/project.properties b/android/project.properties index 84b11fd245..babca9a8c9 100644 --- a/android/project.properties +++ b/android/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-18 +target=android-10 android.library.reference.1=../native/android From 6c2a9972c124f7a9c332bca668afa23d897a55a5 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 19:09:56 +0530 Subject: [PATCH 5/7] using the new atomic_flag --- Core/HLE/__sceAudio.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index fb0769f3b8..a5f945f40b 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -29,10 +29,11 @@ #include "FixedSizeQueue.h" #include "Common/Thread.h" #include "Common/Atomics.h" +#include "../../native/base/mutex.h" // Should be used to lock anything related to the outAudioQueue. //atomic locks are used on the lock. TODO: make this lock-free -volatile u32 audioQueueLocked; +atomic_flag audioQueueLock(NATIVE_ATOMIC_FLAG_INIT); int eventAudioUpdate = -1; int eventHostAudioUpdate = -1; @@ -115,8 +116,7 @@ void __AudioInit() { mixBuffer = new s32[hwBlockSize * 2]; memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32)); - //set the lock to false initially - Common::AtomicStore(audioQueueLocked, 0); + } void __AudioDoState(PointerWrap &p) { @@ -408,14 +408,11 @@ int __AudioMix(short *outstereo, int numFrames) inline bool __gainAudioQueueLock(){ - if(Common::AtomicLoad(audioQueueLocked) == 1){ - return false; - } + //if it becomes true, it returns true - Common::AtomicStore(audioQueueLocked, 1); - return true; + return !audioQueueLock.test_and_set(); }; inline void __releaseAcquiredLock(){ - Common::AtomicStore(audioQueueLocked, 0); + audioQueueLock.clear(); } From eb9c339c2e79d5bc8e20456137d239a5ca2e0ec6 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Wed, 2 Oct 2013 20:20:32 +0530 Subject: [PATCH 6/7] fully functional and uses atomic_flag --- Core/HLE/__sceAudio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index a5f945f40b..5565d5aec3 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -36,7 +36,7 @@ atomic_flag audioQueueLock(NATIVE_ATOMIC_FLAG_INIT); int eventAudioUpdate = -1; -int eventHostAudioUpdate = -1; +int eventHostAudioUpdate = -1; int mixFrequency = 44100; const int hwSampleRate = 44100; From eb1305120ebfc5aab0a8eb99c9f0c22ce7278192 Mon Sep 17 00:00:00 2001 From: Siddharth Date: Fri, 4 Oct 2013 17:58:09 +0530 Subject: [PATCH 7/7] now blocks to gain outAudioQueue access at __AudioDoState --- Core/HLE/__sceAudio.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 5565d5aec3..923c40c81b 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -58,7 +58,6 @@ static int chanQueueMinSizeFactor; // is bad mojo. FixedSizeQueue outAudioQueue; - bool __gainAudioQueueLock(); void __releaseAcquiredLock(); @@ -131,9 +130,11 @@ void __AudioDoState(PointerWrap &p) { p.Do(mixFrequency); - { - if(!__gainAudioQueueLock()){ - return; + { + //block until a lock is achieved. Not a good idea at all, but + //can't think of a better one... + while(!__gainAudioQueueLock()){ + continue; } outAudioQueue.DoState(p); @@ -407,9 +408,16 @@ int __AudioMix(short *outstereo, int numFrames) } +/*returns whether the lock was successfully gained or not. +i.e - whether the lock belongs to you +*/ inline bool __gainAudioQueueLock(){ - //if it becomes true, it returns true + /*if the previous state was 0, that means the lock was "unlocked". So, + we return !0, which is true thanks to C's int to bool conversion + One the other hand, if it was locked, then the lock would return 1. + so, !1 = 0 = false. + */ return !audioQueueLock.test_and_set(); };