all repos — mgba @ 40ae214a7dfb422f30ac4a138fdaedd45fc66065

mGBA Game Boy Advance Emulator

GBA Thread: Split GBASync into a separate file
Jeffrey Pfau jeffrey@endrift.com
Wed, 10 Jun 2015 01:06:09 -0700
commit

40ae214a7dfb422f30ac4a138fdaedd45fc66065

parent

79e06612cb77d31bfaaa1a5506703158b4a2f989

M CHANGESCHANGES

@@ -63,6 +63,7 @@ - Perf: Ability to load savestates immediately on launch

- Qt: Replace pause-after-frame mutex with an atomic - Util: Allow disabling the threading code entirely - GBA: SIO logging layer + - GBA Thread: Split GBASync into a separate file 0.2.1: (2015-05-13) Bugfixes:
A src/gba/supervisor/sync.c

@@ -0,0 +1,126 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "thread.h" + +static void _changeVideoSync(struct GBASync* sync, bool frameOn) { + // Make sure the video thread can process events while the GBA thread is paused + MutexLock(&sync->videoFrameMutex); + if (frameOn != sync->videoFrameOn) { + sync->videoFrameOn = frameOn; + ConditionWake(&sync->videoFrameAvailableCond); + } + MutexUnlock(&sync->videoFrameMutex); +} + +void GBASyncPostFrame(struct GBASync* sync) { + if (!sync) { + return; + } + + MutexLock(&sync->videoFrameMutex); + ++sync->videoFramePending; + --sync->videoFrameSkip; + if (sync->videoFrameSkip < 0) { + do { + ConditionWake(&sync->videoFrameAvailableCond); + if (sync->videoFrameWait) { + ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex); + } + } while (sync->videoFrameWait && sync->videoFramePending); + } + MutexUnlock(&sync->videoFrameMutex); +} + +void GBASyncForceFrame(struct GBASync* sync) { + if (!sync) { + return; + } + + MutexLock(&sync->videoFrameMutex); + ConditionWake(&sync->videoFrameAvailableCond); + MutexUnlock(&sync->videoFrameMutex); +} + +bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip) { + if (!sync) { + return true; + } + + MutexLock(&sync->videoFrameMutex); + ConditionWake(&sync->videoFrameRequiredCond); + if (!sync->videoFrameOn && !sync->videoFramePending) { + return false; + } + if (sync->videoFrameOn) { + if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) { + return false; + } + } + sync->videoFramePending = 0; + sync->videoFrameSkip = frameskip; + return true; +} + +void GBASyncWaitFrameEnd(struct GBASync* sync) { + if (!sync) { + return; + } + + MutexUnlock(&sync->videoFrameMutex); +} + +bool GBASyncDrawingFrame(struct GBASync* sync) { + if (!sync) { + return true; + } + + return sync->videoFrameSkip <= 0; +} + +void GBASyncSetVideoSync(struct GBASync* sync, bool wait) { + if (!sync) { + return; + } + + _changeVideoSync(sync, wait); +} + +void GBASyncProduceAudio(struct GBASync* sync, bool wait) { + if (!sync) { + return; + } + + if (sync->audioWait && wait) { + // TODO loop properly in event of spurious wakeups + ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex); + } + MutexUnlock(&sync->audioBufferMutex); +} + +void GBASyncLockAudio(struct GBASync* sync) { + if (!sync) { + return; + } + + MutexLock(&sync->audioBufferMutex); +} + +void GBASyncUnlockAudio(struct GBASync* sync) { + if (!sync) { + return; + } + + MutexUnlock(&sync->audioBufferMutex); +} + +void GBASyncConsumeAudio(struct GBASync* sync) { + if (!sync) { + return; + } + + ConditionWake(&sync->audioRequiredCond); + MutexUnlock(&sync->audioBufferMutex); +}
A src/gba/supervisor/sync.h

@@ -0,0 +1,39 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_SYNC_H +#define GBA_SYNC_H + +#include "util/common.h" + +#include "util/threading.h" + +struct GBASync { + int videoFramePending; + bool videoFrameWait; + int videoFrameSkip; + bool videoFrameOn; + Mutex videoFrameMutex; + Condition videoFrameAvailableCond; + Condition videoFrameRequiredCond; + + bool audioWait; + Condition audioRequiredCond; + Mutex audioBufferMutex; +}; + +void GBASyncPostFrame(struct GBASync* sync); +void GBASyncForceFrame(struct GBASync* sync); +bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip); +void GBASyncWaitFrameEnd(struct GBASync* sync); +bool GBASyncDrawingFrame(struct GBASync* sync); +void GBASyncSetVideoSync(struct GBASync* sync, bool wait); + +void GBASyncProduceAudio(struct GBASync* sync, bool wait); +void GBASyncLockAudio(struct GBASync* sync); +void GBASyncUnlockAudio(struct GBASync* sync); +void GBASyncConsumeAudio(struct GBASync* sync); + +#endif
M src/gba/supervisor/thread.csrc/gba/supervisor/thread.c

@@ -93,19 +93,7 @@ if (!onThread) {

_waitUntilNotState(threadContext, THREAD_PAUSING); } } -#endif -static void _changeVideoSync(struct GBASync* sync, bool frameOn) { - // Make sure the video thread can process events while the GBA thread is paused - MutexLock(&sync->videoFrameMutex); - if (frameOn != sync->videoFrameOn) { - sync->videoFrameOn = frameOn; - ConditionWake(&sync->videoFrameAvailableCond); - } - MutexUnlock(&sync->videoFrameMutex); -} - -#ifndef DISABLE_THREADING static THREAD_ENTRY _GBAThreadRun(void* context) { #ifdef USE_PTHREADS pthread_once(&_contextOnce, _createTLS);

@@ -631,7 +619,7 @@ frameOn = false;

} MutexUnlock(&threadContext->stateMutex); - _changeVideoSync(&threadContext->sync, frameOn); + GBASyncSetVideoSync(&threadContext->sync, frameOn); } void GBAThreadUnpause(struct GBAThread* threadContext) {

@@ -645,7 +633,7 @@ frameOn = threadContext->frameWasOn;

} MutexUnlock(&threadContext->stateMutex); - _changeVideoSync(&threadContext->sync, frameOn); + GBASyncSetVideoSync(&threadContext->sync, frameOn); } bool GBAThreadIsPaused(struct GBAThread* threadContext) {

@@ -672,7 +660,7 @@ frameOn = false;

} MutexUnlock(&threadContext->stateMutex); - _changeVideoSync(&threadContext->sync, frameOn); + GBASyncSetVideoSync(&threadContext->sync, frameOn); } void GBAThreadPauseFromThread(struct GBAThread* threadContext) {

@@ -685,7 +673,7 @@ frameOn = false;

} MutexUnlock(&threadContext->stateMutex); - _changeVideoSync(&threadContext->sync, frameOn); + GBASyncSetVideoSync(&threadContext->sync, frameOn); } #ifdef USE_PTHREADS

@@ -722,113 +710,3 @@ struct GBAThread* GBAThreadGetContext(void) {

return 0; } #endif - -void GBASyncPostFrame(struct GBASync* sync) { - if (!sync) { - return; - } - - MutexLock(&sync->videoFrameMutex); - ++sync->videoFramePending; - --sync->videoFrameSkip; - if (sync->videoFrameSkip < 0) { - do { - ConditionWake(&sync->videoFrameAvailableCond); - if (sync->videoFrameWait) { - ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex); - } - } while (sync->videoFrameWait && sync->videoFramePending); - } - MutexUnlock(&sync->videoFrameMutex); -} - -void GBASyncForceFrame(struct GBASync* sync) { - if (!sync) { - return; - } - - MutexLock(&sync->videoFrameMutex); - ConditionWake(&sync->videoFrameAvailableCond); - MutexUnlock(&sync->videoFrameMutex); -} - -bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip) { - if (!sync) { - return true; - } - - MutexLock(&sync->videoFrameMutex); - ConditionWake(&sync->videoFrameRequiredCond); - if (!sync->videoFrameOn && !sync->videoFramePending) { - return false; - } - if (sync->videoFrameOn) { - if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) { - return false; - } - } - sync->videoFramePending = 0; - sync->videoFrameSkip = frameskip; - return true; -} - -void GBASyncWaitFrameEnd(struct GBASync* sync) { - if (!sync) { - return; - } - - MutexUnlock(&sync->videoFrameMutex); -} - -bool GBASyncDrawingFrame(struct GBASync* sync) { - if (!sync) { - return true; - } - - return sync->videoFrameSkip <= 0; -} - -void GBASyncSetVideoSync(struct GBASync* sync, bool wait) { - if (!sync) { - return; - } - - _changeVideoSync(sync, wait); -} - -void GBASyncProduceAudio(struct GBASync* sync, bool wait) { - if (!sync) { - return; - } - - if (sync->audioWait && wait) { - // TODO loop properly in event of spurious wakeups - ConditionWait(&sync->audioRequiredCond, &sync->audioBufferMutex); - } - MutexUnlock(&sync->audioBufferMutex); -} - -void GBASyncLockAudio(struct GBASync* sync) { - if (!sync) { - return; - } - - MutexLock(&sync->audioBufferMutex); -} - -void GBASyncUnlockAudio(struct GBASync* sync) { - if (!sync) { - return; - } - - MutexUnlock(&sync->audioBufferMutex); -} - -void GBASyncConsumeAudio(struct GBASync* sync) { - if (!sync) { - return; - } - - ConditionWake(&sync->audioRequiredCond); - MutexUnlock(&sync->audioBufferMutex); -}
M src/gba/supervisor/thread.hsrc/gba/supervisor/thread.h

@@ -11,6 +11,7 @@

#include "gba/gba.h" #include "gba/input.h" #include "gba/supervisor/overrides.h" +#include "gba/supervisor/sync.h" #include "util/threading.h"

@@ -33,20 +34,6 @@ THREAD_RESETING,

THREAD_EXITING, THREAD_SHUTDOWN, THREAD_CRASHED -}; - -struct GBASync { - int videoFramePending; - bool videoFrameWait; - int videoFrameSkip; - bool videoFrameOn; - Mutex videoFrameMutex; - Condition videoFrameAvailableCond; - Condition videoFrameRequiredCond; - - bool audioWait; - Condition audioRequiredCond; - Mutex audioBufferMutex; }; struct GBAThread {

@@ -142,17 +129,5 @@

#ifdef USE_PNG void GBAThreadTakeScreenshot(struct GBAThread* threadContext); #endif - -void GBASyncPostFrame(struct GBASync* sync); -void GBASyncForceFrame(struct GBASync* sync); -bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip); -void GBASyncWaitFrameEnd(struct GBASync* sync); -bool GBASyncDrawingFrame(struct GBASync* sync); -void GBASyncSetVideoSync(struct GBASync* sync, bool wait); - -void GBASyncProduceAudio(struct GBASync* sync, bool wait); -void GBASyncLockAudio(struct GBASync* sync); -void GBASyncUnlockAudio(struct GBASync* sync); -void GBASyncConsumeAudio(struct GBASync* sync); #endif
M src/gba/video.csrc/gba/video.c

@@ -9,7 +9,7 @@ #include "gba/gba.h"

#include "gba/io.h" #include "gba/serialize.h" #include "gba/supervisor/rr.h" -#include "gba/supervisor/thread.h" +#include "gba/supervisor/sync.h" #include "util/memory.h"
M src/platform/ffmpeg/ffmpeg-encoder.hsrc/platform/ffmpeg/ffmpeg-encoder.h

@@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef FFMPEG_ENCODER #define FFMPEG_ENCODER -#include "gba/supervisor/thread.h" +#include "gba/gba.h" #include <libavformat/avformat.h>
M src/platform/imagemagick/imagemagick-gif-encoder.hsrc/platform/imagemagick/imagemagick-gif-encoder.h

@@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef IMAGEMAGICK_GIF_ENCODER #define IMAGEMAGICK_GIF_ENCODER -#include "gba/supervisor/thread.h" +#include "gba/gba.h" #define MAGICKCORE_HDRI_ENABLE 0 #define MAGICKCORE_QUANTUM_DEPTH 8