From e4c1ebf344a0c7d5fd8c47d68685aec2b0bf2a07 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 1 Nov 2013 04:49:29 +0100 Subject: [PATCH] Expand thread.c - replace pthread with thread.c wrappers --- audio/librsound.c | 168 +++++++++++++++++++--------------------------- audio/rsound.h | 18 +++-- thread.c | 24 +++++++ thread.h | 2 + 4 files changed, 108 insertions(+), 104 deletions(-) diff --git a/audio/librsound.c b/audio/librsound.c index c5db1d218c..71bba6d98a 100644 --- a/audio/librsound.c +++ b/audio/librsound.c @@ -108,8 +108,8 @@ static int rsnd_update_server_info(rsound_t *rd); static int rsnd_poll(struct pollfd *fd, int numfd, int timeout); static void rsnd_sleep(int msec); -static void* rsnd_cb_thread(void *thread_data); -static void* rsnd_thread(void *thread_data); +static void rsnd_cb_thread(void *thread_data); +static void rsnd_thread(void *thread_data); #ifdef __CELLOS_LV2__ static int init_count = 0; @@ -747,15 +747,15 @@ static void rsnd_drain(rsound_t *rd) delta *= rd->rate * rd->channels * rd->samplesize; delta /= 1000000; /* Calculates the amount of data we have in our virtual buffer. Only used to calculate delay. */ - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); rd->bytes_in_buffer = (int)((int64_t)rd->total_written + (int64_t)fifo_read_avail(rd->fifo_buffer) - delta); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); } else { - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); rd->bytes_in_buffer = fifo_read_avail(rd->fifo_buffer); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); } } @@ -771,44 +771,43 @@ static size_t rsnd_fill_buffer(rsound_t *rd, const char *buf, size_t size) if ( !rd->thread_active ) return 0; - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); if ( fifo_write_avail(rd->fifo_buffer) >= size ) { - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); break; } - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); /* Sleeps until we can write to the FIFO. */ - pthread_mutex_lock(&rd->thread.cond_mutex); - pthread_cond_signal(&rd->thread.cond); + slock_lock(rd->thread.cond_mutex); + scond_signal(rd->thread.cond); RSD_DEBUG("[RSound] rsnd_fill_buffer: Going to sleep.\n"); - pthread_cond_wait(&rd->thread.cond, &rd->thread.cond_mutex); + scond_wait(rd->thread.cond, rd->thread.cond_mutex); RSD_DEBUG("[RSound] rsnd_fill_buffer: Woke up.\n"); - pthread_mutex_unlock(&rd->thread.cond_mutex); + slock_unlock(rd->thread.cond_mutex); } - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); fifo_write(rd->fifo_buffer, buf, size); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); //RSD_DEBUG("[RSound] fill_buffer: Wrote to buffer.\n"); /* Send signal to thread that buffer has been updated */ //RSD_DEBUG("[RSound] fill_buffer: Waking up thread.\n"); - pthread_cond_signal(&rd->thread.cond); + scond_signal(rd->thread.cond); return size; } static int rsnd_start_thread(rsound_t *rd) { - int rc; if ( !rd->thread_active ) { rd->thread_active = 1; - rc = pthread_create(&rd->thread.threadId, NULL, rd->audio_callback ? rsnd_cb_thread : rsnd_thread, rd); - if ( rc < 0 ) + rd->thread.thread = (sthread_t*)sthread_create(rd->audio_callback ? rsnd_cb_thread : rsnd_thread, rd); + if ( !rd->thread.thread ) { rd->thread_active = 0; RSD_ERR("[RSound] Failed to create thread."); @@ -828,15 +827,13 @@ static int rsnd_stop_thread(rsound_t *rd) RSD_DEBUG("[RSound] Shutting down thread.\n"); - pthread_mutex_lock(&rd->thread.cond_mutex); + slock_lock(rd->thread.cond_mutex); rd->thread_active = 0; - pthread_cond_signal(&rd->thread.cond); - pthread_mutex_unlock(&rd->thread.cond_mutex); + scond_signal(rd->thread.cond); + slock_unlock(rd->thread.cond_mutex); - if ( pthread_join(rd->thread.threadId, NULL) < 0 ) - RSD_WARN("[RSound] *** Warning, did not terminate thread. ***\n"); - else - RSD_DEBUG("[RSound] Thread joined successfully.\n"); + sthread_join(rd->thread.thread); + RSD_DEBUG("[RSound] Thread joined successfully.\n"); return 0; } @@ -857,10 +854,10 @@ static size_t rsnd_get_delay(rsound_t *rd) /* Adds the backend latency to the calculated latency. */ ptr += (int)rd->backend_info.latency; - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); ptr += rd->delay_offset; RSD_DEBUG("Offset: %d.\n", rd->delay_offset); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); if ( ptr < 0 ) ptr = 0; @@ -871,9 +868,9 @@ static size_t rsnd_get_delay(rsound_t *rd) static size_t rsnd_get_ptr(rsound_t *rd) { int ptr; - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); ptr = fifo_read_avail(rd->fifo_buffer); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); return ptr; } @@ -1049,9 +1046,9 @@ static int rsnd_update_server_info(rsound_t *rd) int delay = rsd_delay(rd); int delta = (int)(client_ptr - serv_ptr); - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); delta += fifo_read_avail(rd->fifo_buffer); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); RSD_DEBUG("[RSound] Delay: %d, Delta: %d.\n", delay, delta); @@ -1065,9 +1062,9 @@ static int rsnd_update_server_info(rsound_t *rd) else if ( offset_delta > max_offset ) offset_delta = max_offset; - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); rd->delay_offset += offset_delta; - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); RSD_DEBUG("[RSound] Changed offset-delta: %d.\n", offset_delta); } } @@ -1081,7 +1078,7 @@ static int rsnd_update_server_info(rsound_t *rd) break /* The blocking thread */ -static void* rsnd_thread ( void * thread_data ) +static void rsnd_thread ( void * thread_data ) { /* We share data between thread and callable functions */ rsound_t *rd = thread_data; @@ -1105,18 +1102,18 @@ static void* rsnd_thread ( void * thread_data ) } /* If the buffer is empty or we've stopped the stream, jump out of this for loop */ - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); if ( fifo_read_avail(rd->fifo_buffer) < rd->backend_info.chunk_size || !rd->thread_active ) { - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); break; } - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); _TEST_CANCEL(); - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); fifo_read(rd->fifo_buffer, buffer, sizeof(buffer)); - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); rc = rsnd_send_chunk(rd->conn.socket, buffer, sizeof(buffer), 1); /* If this happens, we should make sure that subsequent and current calls to rsd_write() will fail. */ @@ -1126,29 +1123,29 @@ static void* rsnd_thread ( void * thread_data ) rsnd_reset(rd); /* Wakes up a potentially sleeping fill_buffer() */ - pthread_cond_signal(&rd->thread.cond); + scond_signal(rd->thread.cond); /* This thread will not be joined, so detach. */ - pthread_detach(pthread_self()); - pthread_exit(NULL); + sthread_detach(rd->thread.thread); + sthread_exit(rd->thread.thread); } /* If this was the first write, set the start point for the timer. */ if ( !rd->has_written ) { - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); rd->start_time = rsnd_get_time_usec(); rd->has_written = 1; - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); } /* Increase the total_written counter. Used in rsnd_drain() */ - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); rd->total_written += rc; - pthread_mutex_unlock(&rd->thread.mutex); + slock_unlock(rd->thread.mutex); /* Buffer has decreased, signal fill_buffer() */ - pthread_cond_signal(&rd->thread.cond); + scond_signal(rd->thread.cond); } @@ -1159,32 +1156,31 @@ static void* rsnd_thread ( void * thread_data ) // There is a very slim change of getting a deadlock using the cond_wait scheme. // This solution is rather dirty, but avoids complete deadlocks at the very least. - pthread_mutex_lock(&rd->thread.cond_mutex); - pthread_cond_signal(&rd->thread.cond); + slock_lock(rd->thread.cond_mutex); + scond_signal(rd->thread.cond); if ( rd->thread_active ) { RSD_DEBUG("[RSound] Thread going to sleep.\n"); - pthread_cond_wait(&rd->thread.cond, &rd->thread.cond_mutex); + scond_wait(rd->thread.cond, rd->thread.cond_mutex); RSD_DEBUG("[RSound] Thread woke up.\n"); } - pthread_mutex_unlock(&rd->thread.cond_mutex); + slock_unlock(rd->thread.cond_mutex); RSD_DEBUG("[RSound] Thread unlocked cond_mutex.\n"); } /* Abort request, chap. */ else { - pthread_cond_signal(&rd->thread.cond); - pthread_exit(NULL); + scond_signal(rd->thread.cond); + sthread_exit(rd->thread.thread); } } - return NULL; } /* Callback thread */ -static void* rsnd_cb_thread(void *thread_data) +static void rsnd_cb_thread(void *thread_data) { rsound_t *rd = thread_data; size_t read_size = rd->backend_info.chunk_size; @@ -1208,9 +1204,9 @@ static void* rsnd_cb_thread(void *thread_data) if (ret < 0) { rsnd_reset(rd); - pthread_detach(pthread_self()); + sthread_detach(rd->thread.thread); rd->error_callback(rd->cb_data); - pthread_exit(NULL); + sthread_exit(rd->thread.thread); } has_read += ret; @@ -1237,9 +1233,9 @@ static void* rsnd_cb_thread(void *thread_data) if (ret != (ssize_t)rd->backend_info.chunk_size) { rsnd_reset(rd); - pthread_detach(pthread_self()); + sthread_detach(rd->thread.thread); rd->error_callback(rd->cb_data); - pthread_exit(NULL); + sthread_exit(rd->thread.thread); } /* If this was the first write, set the start point for the timer. */ @@ -1260,8 +1256,7 @@ static void* rsnd_cb_thread(void *thread_data) if (rd->has_written) rsd_delay_wait(rd); } - pthread_exit(NULL); - return NULL; + sthread_exit(rd->thread.thread); } static int rsnd_reset(rsound_t *rd) @@ -1273,7 +1268,7 @@ static int rsnd_reset(rsound_t *rd) socketclose(rd->conn.ctl_socket); /* Pristine stuff, baby! */ - pthread_mutex_lock(&rd->thread.mutex); + slock_lock(rd->thread.mutex); rd->conn.socket = -1; rd->conn.ctl_socket = -1; rd->total_written = 0; @@ -1282,8 +1277,8 @@ static int rsnd_reset(rsound_t *rd) rd->bytes_in_buffer = 0; rd->thread_active = 0; rd->delay_offset = 0; - pthread_mutex_unlock(&rd->thread.mutex); - pthread_cond_signal(&rd->thread.cond); + slock_unlock(rd->thread.mutex); + scond_signal(rd->thread.cond); return 0; } @@ -1308,9 +1303,7 @@ size_t rsd_write( rsound_t *rsound, const void* buf, size_t size) { assert(rsound != NULL); if ( !rsound->ready_for_data ) - { return 0; - } size_t result; size_t max_write = (rsound->buffer_size - rsound->backend_info.chunk_size)/2; @@ -1559,10 +1552,10 @@ int rsd_init(rsound_t** rsound) (*rsound)->conn.socket = -1; (*rsound)->conn.ctl_socket = -1; - pthread_mutex_init(&(*rsound)->thread.mutex, NULL); - pthread_mutex_init(&(*rsound)->thread.cond_mutex, NULL); - pthread_mutex_init(&(*rsound)->cb_lock, NULL); - pthread_cond_init(&(*rsound)->thread.cond, NULL); + (*rsound)->thread.mutex = slock_new(); + (*rsound)->thread.cond_mutex = slock_new(); + (*rsound)->cb_lock = slock_new(); + (*rsound)->thread.cond = scond_new(); // Assumes default of S16_LE samples. int format = RSD_S16_LE; @@ -1630,12 +1623,12 @@ void rsd_set_callback(rsound_t *rsound, rsd_audio_callback_t audio_cb, rsd_error void rsd_callback_lock(rsound_t *rsound) { - pthread_mutex_lock(&rsound->cb_lock); + slock_lock(rsound->cb_lock); } void rsd_callback_unlock(rsound_t *rsound) { - pthread_mutex_unlock(&rsound->cb_lock); + slock_unlock(rsound->cb_lock); } int rsd_free(rsound_t *rsound) @@ -1648,31 +1641,10 @@ int rsd_free(rsound_t *rsound) if (rsound->port) free(rsound->port); - int err = pthread_mutex_destroy(&rsound->thread.mutex); - - if (err != 0 ) - { - RSD_WARN("Error: %s\n", strerror(err)); - return -1; - } - - if ( (err = pthread_mutex_destroy(&rsound->thread.cond_mutex)) != 0 ) - { - RSD_WARN("Error: %s\n", strerror(err)); - return -1; - } - - if ( (err = pthread_mutex_destroy(&rsound->cb_lock)) != 0 ) - { - RSD_WARN("Error: %s\n", strerror(err)); - return -1; - } - - if ( (err = pthread_cond_destroy(&rsound->thread.cond)) != 0 ) - { - RSD_WARN("Error: %s\n", strerror(err)); - return -1; - } + slock_free(rsound->thread.mutex); + slock_free(rsound->thread.cond_mutex); + slock_free(rsound->cb_lock); + scond_free(rsound->thread.cond); free(rsound); diff --git a/audio/rsound.h b/audio/rsound.h index 05e9c98998..43c80200b6 100644 --- a/audio/rsound.h +++ b/audio/rsound.h @@ -20,9 +20,15 @@ extern "C" { #endif +//#define STANDALONE + #include #include -#include +#ifdef STANDALONE +#include "thread.h" +#else +#include "../thread.h" +#endif #include #include #include @@ -169,10 +175,10 @@ extern "C" { int samplesize; struct { - pthread_t threadId; - pthread_mutex_t mutex; - pthread_mutex_t cond_mutex; - pthread_cond_t cond; + sthread_t *thread; + slock_t *mutex; + slock_t *cond_mutex; + scond_t *cond; } thread; char identity[256]; @@ -181,7 +187,7 @@ extern "C" { rsd_error_callback_t error_callback; size_t cb_max_size; void *cb_data; - pthread_mutex_t cb_lock; + slock_t *cb_lock; } rsound_t; /* -- API -- diff --git a/thread.c b/thread.c index 451de9f1d0..bd1e1aa82e 100644 --- a/thread.c +++ b/thread.c @@ -1,5 +1,6 @@ /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2013 - Hans-Kristian Arntzen + * Copyright (C) 2011-2013 - Daniel De Matteis * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -83,6 +84,12 @@ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) return thread; } +int sthread_detach(sthread_t *thread) +{ + CloseHandle(thread->thread); + return 0; +} + void sthread_join(sthread_t *thread) { WaitForSingleObject(thread->thread, INFINITE); @@ -90,6 +97,12 @@ void sthread_join(sthread_t *thread) free(thread); } +/* FIXME - what to do here? */ +void sthread_exit(sthread_t *thread) +{ + (void)thread; +} + struct slock { CRITICAL_SECTION lock; @@ -222,12 +235,23 @@ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) return thr; } +int sthread_detach(sthread_t *thread) +{ + (void)thread; + return pthread_detach(pthread_self()); +} + void sthread_join(sthread_t *thread) { pthread_join(thread->id, NULL); free(thread); } +void sthread_exit(sthread_t *thread) +{ + pthread_exit(NULL); +} + struct slock { pthread_mutex_t lock; diff --git a/thread.h b/thread.h index 51ae339839..57c8a605ed 100644 --- a/thread.h +++ b/thread.h @@ -25,7 +25,9 @@ typedef struct sthread sthread_t; // Threading sthread_t *sthread_create(void (*thread_func)(void*), void *userdata); +int sthread_detach(sthread_t *thread); void sthread_join(sthread_t *thread); +void sthread_exit(sthread_t *thread); // Mutexes typedef struct slock slock_t;