From 00dd5bdaa81e97f46474f527443e8cf07f6e1ae9 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Wed, 24 Apr 2013 02:43:55 -0700 Subject: [PATCH] Dual condition-variable non-hacky waiting-on-frame --- src/gba/renderers/video-software.c | 12 ++++++++---- src/gba/renderers/video-software.h | 3 ++- src/main.c | 16 +++++++++++++--- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index bba7f3698..1e17e3195 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -46,7 +46,8 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) { pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; renderer->mutex = mutex; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - renderer->cond = cond; + renderer->upCond = cond; + renderer->downCond = cond; } } @@ -93,14 +94,16 @@ static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) { } pthread_mutex_init(&softwareRenderer->mutex, 0); - pthread_cond_init(&softwareRenderer->cond, 0); + pthread_cond_init(&softwareRenderer->upCond, 0); + pthread_cond_init(&softwareRenderer->downCond, 0); } static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) { struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer; pthread_mutex_destroy(&softwareRenderer->mutex); - pthread_cond_destroy(&softwareRenderer->cond); + pthread_cond_destroy(&softwareRenderer->upCond); + pthread_cond_destroy(&softwareRenderer->downCond); } static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) { @@ -210,8 +213,9 @@ static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* rendere pthread_mutex_lock(&softwareRenderer->mutex); renderer->framesPending++; + pthread_cond_broadcast(&softwareRenderer->upCond); if (!renderer->turbo) { - pthread_cond_wait(&softwareRenderer->cond, &softwareRenderer->mutex); + pthread_cond_wait(&softwareRenderer->downCond, &softwareRenderer->mutex); } pthread_mutex_unlock(&softwareRenderer->mutex); } diff --git a/src/gba/renderers/video-software.h b/src/gba/renderers/video-software.h index 866ebc4d6..6ce21f3f9 100644 --- a/src/gba/renderers/video-software.h +++ b/src/gba/renderers/video-software.h @@ -71,7 +71,8 @@ struct GBAVideoSoftwareRenderer { uint16_t* row; pthread_mutex_t mutex; - pthread_cond_t cond; + pthread_cond_t upCond; + pthread_cond_t downCond; }; void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer); diff --git a/src/main.c b/src/main.c index 3e5e28a35..2ae792e83 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include struct GLSoftwareRenderer { @@ -118,12 +119,21 @@ static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer* SDL_GL_SwapBuffers(); pthread_mutex_lock(&renderer->d.mutex); - pthread_cond_broadcast(&renderer->d.cond); + pthread_cond_broadcast(&renderer->d.downCond); pthread_mutex_unlock(&renderer->d.mutex); } else { + while (!renderer->d.d.framesPending) { + struct timeval tv; + struct timespec ts; + gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000 + 800000; + int err = pthread_cond_timedwait(&renderer->d.upCond, &renderer->d.mutex, &ts); + if (err == ETIMEDOUT) { + break; + } + } pthread_mutex_unlock(&renderer->d.mutex); - // We have no frame, let's just wait a sec to see if we get one. - usleep(500); } while (SDL_PollEvent(&event)) { switch (event.type) {