mirror of
https://github.com/mauiaaron/apple2.git
synced 2025-02-05 20:31:53 +00:00
Refactor/simplify spinlocking
This commit is contained in:
parent
ef3944a4dd
commit
5a8aa065a9
@ -71,10 +71,10 @@ static AudioBackend_s opensles_audio_backend = { 0 };
|
||||
// Check and resets underrun condition (readHead has advanced beyond writeHead)
|
||||
static inline bool _underrun_check_and_manage(SLVoice *voice, OUTPARM unsigned long *workingBytes) {
|
||||
|
||||
SPINLOCK_ACQUIRE(&voice->spinLock);
|
||||
SPIN_LOCK_FULL(&voice->spinLock);
|
||||
unsigned long readHead = voice->readHead;
|
||||
unsigned long readWrapCount = voice->readWrapCount;
|
||||
SPINLOCK_RELINQUISH(&voice->spinLock);
|
||||
SPIN_UNLOCK_FULL(&voice->spinLock);
|
||||
|
||||
assert(readHead < voice->bufferSize);
|
||||
assert(voice->writeHead < voice->bufferSize);
|
||||
@ -160,10 +160,10 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
|
||||
++newReadWrapCount0;
|
||||
}
|
||||
|
||||
SPINLOCK_ACQUIRE(&voice0->spinLock);
|
||||
SPIN_LOCK_FULL(&voice0->spinLock);
|
||||
voice0->readHead = newReadHead0;
|
||||
voice0->readWrapCount = newReadWrapCount0;
|
||||
SPINLOCK_RELINQUISH(&voice0->spinLock);
|
||||
SPIN_UNLOCK_FULL(&voice0->spinLock);
|
||||
|
||||
if (voice1) {
|
||||
memset(voice1->ringBuffer+voice1->readHead, 0x0, ctx->submitSize); // backfill quiet samples
|
||||
@ -178,10 +178,10 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
|
||||
++newReadWrapCount1;
|
||||
}
|
||||
|
||||
SPINLOCK_ACQUIRE(&voice1->spinLock);
|
||||
SPIN_LOCK_FULL(&voice1->spinLock);
|
||||
voice1->readHead = newReadHead1;
|
||||
voice1->readWrapCount = newReadWrapCount1;
|
||||
SPINLOCK_RELINQUISH(&voice1->spinLock);
|
||||
SPIN_UNLOCK_FULL(&voice1->spinLock);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
@ -316,10 +316,10 @@ static long SLUnlockStaticBuffer(AudioBuffer_s *_this, unsigned long audio_bytes
|
||||
static long SLReplay(AudioBuffer_s *_this) {
|
||||
SLVoice *voice = (SLVoice*)_this->_internal;
|
||||
|
||||
SPINLOCK_ACQUIRE(&voice->spinLock);
|
||||
SPIN_LOCK_FULL(&voice->spinLock);
|
||||
voice->readHead = 0;
|
||||
voice->writeHead = voice->replay_index;
|
||||
SPINLOCK_RELINQUISH(&voice->spinLock);
|
||||
SPIN_UNLOCK_FULL(&voice->spinLock);
|
||||
|
||||
long err = _SLMaybeSubmitAndStart(voice);
|
||||
#warning FIXME TODO ... how do we handle mockingboard for new OpenSLES buffer queue codepath?
|
||||
|
30
src/common.h
30
src/common.h
@ -26,13 +26,13 @@
|
||||
#define PUBLIC
|
||||
#define READONLY
|
||||
|
||||
#define CALL_ON_UI_THREAD
|
||||
#define CALL_ON_UI_THREAD // function should only be called on UI thread
|
||||
#define ASSERT_ON_UI_THREAD() \
|
||||
assert(video_isRenderThread())
|
||||
#define ASSERT_NOT_ON_UI_THREAD() \
|
||||
assert(!video_isRenderThread())
|
||||
|
||||
#define CALL_ON_CPU_THREAD
|
||||
#define CALL_ON_CPU_THREAD // function should only be called on CPU thread
|
||||
#define ASSERT_ON_CPU_THREAD() \
|
||||
assert(timing_isCPUThread())
|
||||
#define ASSERT_NOT_ON_CPU_THREAD() \
|
||||
@ -117,20 +117,26 @@
|
||||
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define SPINLOCK_INIT 0
|
||||
#define SPINLOCK_ACQUIRED -1
|
||||
#define SPINLOCK_ACQUIRE(x) \
|
||||
#define SPINLOCK_INIT 0L
|
||||
|
||||
/*
|
||||
https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
|
||||
|
||||
"In most cases, these built-in functions are considered a full barrier. That is, no memory operand is moved across
|
||||
the operation, either forward or backward. Further, instructions are issued as necessary to prevent the processor
|
||||
from speculating loads across the operation and from queuing stores after the operation."
|
||||
*/
|
||||
#define SPIN_LOCK_FULL(x) \
|
||||
do { \
|
||||
long val = __sync_sub_and_fetch((x), 1); \
|
||||
if (val == SPINLOCK_ACQUIRED) { \
|
||||
long prev = __sync_fetch_and_or((x), 1L); \
|
||||
if (prev == SPINLOCK_INIT) { \
|
||||
break; \
|
||||
} \
|
||||
__sync_add_and_fetch((x), 1); \
|
||||
} while (1);
|
||||
|
||||
#define SPINLOCK_RELINQUISH(x) \
|
||||
__sync_add_and_fetch((x), 1);
|
||||
usleep(1); \
|
||||
} while (1)
|
||||
|
||||
#define SPIN_UNLOCK_FULL(x) \
|
||||
__sync_fetch_and_and((x), SPINLOCK_INIT)
|
||||
|
||||
// cribbed from AOSP and modified with usleep() and to also ignore EAGAIN (should this be a different errno than EINTR)
|
||||
#define TEMP_FAILURE_RETRY_FOPEN(exp) ({ \
|
||||
|
15
src/timing.c
15
src/timing.c
@ -30,7 +30,7 @@ static int32_t cycles_checkpoint_count = 0;
|
||||
// scaling and speed adjustments
|
||||
static bool auto_adjust_speed = true;
|
||||
static bool is_paused = false;
|
||||
static unsigned long _pause_spinLock = 0;
|
||||
static unsigned long _pause_spinLock = SPINLOCK_INIT;
|
||||
|
||||
double cpu_scale_factor = 1.0;
|
||||
double cpu_altscale_factor = 1.0;
|
||||
@ -150,8 +150,9 @@ void timing_toggleCPUSpeed(void) {
|
||||
}
|
||||
|
||||
static void timing_reinitializeAudio(void) {
|
||||
SPINLOCK_ACQUIRE(&_pause_spinLock);
|
||||
ASSERT_NOT_ON_CPU_THREAD();
|
||||
|
||||
SPIN_LOCK_FULL(&_pause_spinLock);
|
||||
#if !TESTING
|
||||
assert(cpu_isPaused());
|
||||
#endif
|
||||
@ -159,13 +160,13 @@ static void timing_reinitializeAudio(void) {
|
||||
emul_pause_audio = false;
|
||||
emul_resume_audio = false;
|
||||
emul_video_dirty = false;
|
||||
SPINLOCK_RELINQUISH(&_pause_spinLock);
|
||||
SPIN_UNLOCK_FULL(&_pause_spinLock);
|
||||
}
|
||||
|
||||
void cpu_pause(void) {
|
||||
ASSERT_NOT_ON_CPU_THREAD();
|
||||
|
||||
SPINLOCK_ACQUIRE(&_pause_spinLock);
|
||||
SPIN_LOCK_FULL(&_pause_spinLock);
|
||||
do {
|
||||
if (is_paused) {
|
||||
break;
|
||||
@ -179,13 +180,13 @@ void cpu_pause(void) {
|
||||
pthread_mutex_lock(&interface_mutex);
|
||||
is_paused = true;
|
||||
} while (0);
|
||||
SPINLOCK_RELINQUISH(&_pause_spinLock);
|
||||
SPIN_UNLOCK_FULL(&_pause_spinLock);
|
||||
}
|
||||
|
||||
void cpu_resume(void) {
|
||||
ASSERT_NOT_ON_CPU_THREAD();
|
||||
|
||||
SPINLOCK_ACQUIRE(&_pause_spinLock);
|
||||
SPIN_LOCK_FULL(&_pause_spinLock);
|
||||
do {
|
||||
if (!is_paused) {
|
||||
break;
|
||||
@ -200,7 +201,7 @@ void cpu_resume(void) {
|
||||
is_paused = false;
|
||||
pthread_mutex_unlock(&interface_mutex);
|
||||
} while (0);
|
||||
SPINLOCK_RELINQUISH(&_pause_spinLock);
|
||||
SPIN_UNLOCK_FULL(&_pause_spinLock);
|
||||
}
|
||||
|
||||
bool cpu_isPaused(void) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user