static void android_app_set_input(void *data, AInputQueue* inputQueue) { struct android_app *android_app = (struct android_app*)data; if (!android_app) return; slock_lock(android_app->mutex); android_app->pendingInputQueue = inputQueue; android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); while (android_app->inputQueue != android_app->pendingInputQueue) scond_wait(android_app->cond, android_app->mutex); slock_unlock(android_app->mutex); }
/* This value is set async as stalling on the video driver for * every query is too slow. * * This means this value might not be correct, so viewport * reads are not supported for now. */ static void video_thread_viewport_info(void *data, struct video_viewport *vp) { thread_video_t *thr = (thread_video_t*)data; if (!thr) return; slock_lock(thr->lock); *vp = thr->vp; /* Explicitly mem-copied so we can use memcmp correctly later. */ memcpy(&thr->read_vp, &thr->vp, sizeof(thr->vp)); slock_unlock(thr->lock); }
/* user -> thread */ static void video_thread_send_packet(thread_video_t *thr, const thread_packet_t *pkt) { slock_lock(thr->lock); thr->cmd_data = *pkt; thr->send_cmd = pkt->type; thr->reply_cmd = CMD_VIDEO_NONE; scond_signal(thr->cond_thread); slock_unlock(thr->lock); }
bool ffemu_push_audio(ffemu_t *handle, const struct ffemu_audio_data *data) { if (!handle->config.audio_enable) return true; for (;;) { slock_lock(handle->lock); unsigned avail = fifo_write_avail(handle->audio_fifo); slock_unlock(handle->lock); if (!handle->alive) return false; if (avail >= data->frames * handle->params.channels * sizeof(int16_t)) break; slock_lock(handle->cond_lock); if (handle->can_sleep) { handle->can_sleep = false; scond_wait(handle->cond, handle->cond_lock); handle->can_sleep = true; } else scond_signal(handle->cond); slock_unlock(handle->cond_lock); } slock_lock(handle->lock); fifo_write(handle->audio_fifo, data->data, data->frames * handle->params.channels * sizeof(int16_t)); slock_unlock(handle->lock); scond_signal(handle->cond); return true; }
static ssize_t sl_write(void *data, const void *buf_, size_t size) { sl_t *sl = (sl_t*)data; size_t written = 0; const uint8_t *buf = (const uint8_t*)buf_; while (size) { if (sl->nonblock) { if (sl->buffered_blocks == sl->buf_count) break; } else { slock_lock(sl->lock); while (sl->buffered_blocks == sl->buf_count) scond_wait(sl->cond, sl->lock); slock_unlock(sl->lock); } size_t avail_write = min(sl->buf_size - sl->buffer_ptr, size); if (avail_write) { memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write); sl->buffer_ptr += avail_write; buf += avail_write; size -= avail_write; written += avail_write; } if (sl->buffer_ptr >= sl->buf_size) { SLresult res = (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[sl->buffer_index], sl->buf_size); sl->buffer_index = (sl->buffer_index + 1) % sl->buf_count; __sync_fetch_and_add(&sl->buffered_blocks, 1); sl->buffer_ptr = 0; if (res != SL_RESULT_SUCCESS) { RARCH_ERR("[OpenSL]: Failed to write! (Error: 0x%x)\n", (unsigned)res); return -1; } } } return written; }
void autosave_free(autosave_t *handle) { slock_lock(handle->cond_lock); handle->quit = true; slock_unlock(handle->cond_lock); scond_signal(handle->cond); sthread_join(handle->thread); slock_free(handle->lock); slock_free(handle->cond_lock); scond_free(handle->cond); free(handle->buffer); free(handle); }
static void thread_set_viewport(void *data, unsigned width, unsigned height, bool force_full, bool allow_rotate) { thread_video_t *thr = (thread_video_t*)data; if (!thr) return; slock_lock(thr->lock); if (thr->driver && thr->driver->set_viewport) thr->driver->set_viewport(thr->driver_data, width, height, force_full, allow_rotate); slock_unlock(thr->lock); }
void rarch_softfilter_process(rarch_softfilter_t *filt, void *output, size_t output_stride, const void *input, unsigned width, unsigned height, size_t input_stride) { unsigned i; if (filt && filt->impl && filt->impl->get_work_packets) filt->impl->get_work_packets(filt->impl_data, filt->packets, output, output_stride, input, width, height, input_stride); #ifdef HAVE_THREADS // Fire off workers for (i = 0; i < filt->threads; i++) { //RARCH_LOG("Firing off filter thread %u ...\n", i); filt->thread_data[i].packet = &filt->packets[i]; slock_lock(filt->thread_data[i].lock); filt->thread_data[i].done = false; scond_signal(filt->thread_data[i].cond); slock_unlock(filt->thread_data[i].lock); } // Wait for workers for (i = 0; i < filt->threads; i++) { //RARCH_LOG("Waiting for filter thread %u ...\n", i); slock_lock(filt->thread_data[i].lock); while (!filt->thread_data[i].done) scond_wait(filt->thread_data[i].cond, filt->thread_data[i].lock); slock_unlock(filt->thread_data[i].lock); } #else for (i = 0; i < filt->threads; i++) filt->packets[i].work(filt->impl_data, filt->packets[i].thread_data); #endif }
static void filter_thread_loop(void *data) { struct filter_thread_data *thr = (struct filter_thread_data*)data; for (;;) { slock_lock(thr->lock); while (thr->done && !thr->die) scond_wait(thr->cond, thr->lock); bool die = thr->die; slock_unlock(thr->lock); if (die) break; if (thr->packet && thr->packet->work) thr->packet->work(thr->userdata, thr->packet->thread_data); slock_lock(thr->lock); thr->done = true; scond_signal(thr->cond); slock_unlock(thr->lock); } }
TA_context* DequeueRender(void) { #ifndef TARGET_NO_THREADS slock_lock(mtx_rqueue); #endif TA_context* rv = rqueue; #ifndef TARGET_NO_THREADS slock_unlock(mtx_rqueue); #endif if (rv) FrameCount++; return rv; }
static void android_app_set_activity_state (void *data, int8_t cmd) { struct android_app *android_app = (struct android_app*)data; if (!android_app) return; slock_lock(android_app->mutex); android_app_write_cmd(android_app, cmd); while (android_app->activityState != cmd && android_app->activityState != APP_CMD_DEAD) scond_wait(android_app->cond, android_app->mutex); slock_unlock(android_app->mutex); if (android_app->activityState == APP_CMD_DEAD) RARCH_LOG("RetroArch native thread is dead.\n"); }
void ssem_signal(ssem_t *semaphore) { if (!semaphore) return; slock_lock(semaphore->mutex); semaphore->value++; if (semaphore->value <= 0) { semaphore->wakeups++; scond_signal(semaphore->cond); } slock_unlock(semaphore->mutex); }
static void data_runloop_thread_deinit(data_runloop_t *runloop) { if (!runloop->thread_inited) { slock_lock(runloop->cond_lock); runloop->alive = false; scond_signal(runloop->cond); slock_unlock(runloop->cond_lock); sthread_join(runloop->thread); slock_free(runloop->lock); slock_free(runloop->cond_lock); rarch_main_data_overlay_thread_uninit(); scond_free(runloop->cond); } }
const char *rarch_main_msg_queue_pull(void) { const char *ret = NULL; #ifdef HAVE_THREADS slock_lock(mq_lock); #endif ret = msg_queue_pull(g_msg_queue); #ifdef HAVE_THREADS slock_unlock(mq_lock); #endif return ret; }
static void data_runloop_thread_deinit(void) { if (!g_data_runloop.thread_inited) { slock_lock(g_data_runloop.cond_lock); g_data_runloop.alive = false; scond_signal(g_data_runloop.cond); slock_unlock(g_data_runloop.cond_lock); sthread_join(g_data_runloop.thread); slock_free(g_data_runloop.lock); slock_free(g_data_runloop.cond_lock); rarch_main_data_overlay_thread_uninit(); scond_free(g_data_runloop.cond); } }
static bool thread_alive(void *data) { thread_video_t *thr = (thread_video_t*)data; if (g_extern.is_paused) { thread_send_cmd(thr, CMD_ALIVE); thread_wait_reply(thr, CMD_ALIVE); return thr->cmd_data.b; } else { slock_lock(thr->lock); bool ret = thr->alive; slock_unlock(thr->lock); return ret; } }
static void retro_task_threaded_cancel(void *task) { retro_task_t *t; slock_lock(running_lock); for (t = tasks_running.front; t; t = t->next) { if (t == task) { t->cancelled = true; break; } } slock_unlock(running_lock); }
static ssize_t rs_write(void *data, const void *buf, size_t size) { rsd_t *rsd = (rsd_t*)data; if (rsd->has_error) return -1; if (rsd->nonblock) { rsd_callback_lock(rsd->rd); size_t avail = fifo_write_avail(rsd->buffer); size_t write_amt = avail > size ? size : avail; fifo_write(rsd->buffer, buf, write_amt); rsd_callback_unlock(rsd->rd); return write_amt; } else { size_t written = 0; while (written < size && !rsd->has_error) { rsd_callback_lock(rsd->rd); size_t avail = fifo_write_avail(rsd->buffer); if (avail == 0) { rsd_callback_unlock(rsd->rd); if (!rsd->has_error) { slock_lock(rsd->cond_lock); scond_wait(rsd->cond, rsd->cond_lock); slock_unlock(rsd->cond_lock); } } else { size_t write_amt = size - written > avail ? avail : size - written; fifo_write(rsd->buffer, (const char*)buf + written, write_amt); rsd_callback_unlock(rsd->rd); written += write_amt; } } return written; } }
static void adapter_thread(void *data) { uint8_t __attribute__((aligned(32))) send_command_buf[4096]; struct wiiusb_adapter *adapter = (struct wiiusb_adapter*)data; wiiusb_hid_t *hid = adapter ? adapter->hid : NULL; if (!adapter) return; while (!adapter->quitting) { size_t send_command_size; int tmp; int report_number; int size = 0; (void)tmp; (void)report_number; slock_lock(adapter->send_control_lock); if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size)) { fifo_read(adapter->send_control_buffer, &send_command_size, sizeof(send_command_size)); if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size)) { fifo_read(adapter->send_control_buffer, send_command_buf, send_command_size); USB_WriteIntrMsg(adapter->handle, adapter->endpoint_out, send_command_size, send_command_buf); } } slock_unlock(adapter->send_control_lock); size = USB_ReadIntrMsg(adapter->handle, adapter->endpoint_in, adapter->endpoint_in_max_size, &adapter->data[0]); /* RARCH_LOG("%p USB_ReadIntrMsg(%i, %i, %i, %p): %i\n", &adapter->data[0], adapter->handle, adapter->endpoint_in, adapter->endpoint_in_max_size, &adapter->data[0], size); */ //RARCH_LOG("%03i %03i %03i %03i\n", adapter->data[0], adapter->data[1], adapter->data[2], adapter->data[3], adapter->data[4]); //memmove(&adapter->data[1], &adapter->data[0], 2048); if (adapter && hid && hid->slots && size) pad_connection_packet(&hid->slots[adapter->slot], adapter->slot, adapter->data - 1, size+1); } }
static void retro_task_threaded_deinit(void) { slock_lock(running_lock); worker_continue = false; scond_signal(worker_cond); slock_unlock(running_lock); sthread_join(worker_thread); scond_free(worker_cond); slock_free(running_lock); slock_free(finished_lock); worker_thread = NULL; worker_cond = NULL; running_lock = NULL; finished_lock = NULL; }
void rarch_main_msg_queue_free(void) { if (!g_msg_queue) return; #ifdef HAVE_THREADS slock_lock(mq_lock); #endif msg_queue_free(g_msg_queue); #ifdef HAVE_THREADS slock_unlock(mq_lock); slock_free(mq_lock); #endif g_msg_queue = NULL; }
static bool thread_alive(void *data) { bool ret; thread_video_t *thr = (thread_video_t*)data; if (rarch_main_is_paused()) { thread_packet_t pkt = { CMD_ALIVE }; thread_send_and_wait(thr, &pkt); return pkt.data.b; } slock_lock(thr->lock); ret = thr->alive; slock_unlock(thr->lock); return ret; }
bool CDIF_MT::ReadRawSector(uint8 *buf, uint32 lba) { bool found = FALSE; bool error_condition = false; if(UnrecoverableError) { memset(buf, 0, 2352 + 96); return(false); } // This shouldn't happen, the emulated-system-specific CDROM emulation code should make sure the emulated program doesn't try // to read past the last "real" sector of the disc. if(lba >= disc_toc.tracks[100].lba) { printf("Attempt to read LBA %d, >= LBA %d\n", lba, disc_toc.tracks[100].lba); return(FALSE); } ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba)); slock_lock((slock_t*)SBMutex); do { int i; for(i = 0; i < SBSize; i++) { if(SectorBuffers[i].valid && SectorBuffers[i].lba == lba) { error_condition = SectorBuffers[i].error; memcpy(buf, SectorBuffers[i].data, 2352 + 96); found = TRUE; } } if(!found) scond_wait((scond_t*)SBCond, (slock_t*)SBMutex); } while(!found); slock_unlock((slock_t*)SBMutex); return(!error_condition); }
static void adapter_thread(void *data) { uint8_t send_command_buf[4096]; struct libusb_adapter *adapter = (struct libusb_adapter*)data; libusb_hid_t *hid = adapter ? adapter->hid : NULL; if (!adapter) return; while (!adapter->quitting) { size_t send_command_size; int tmp; int report_number; int size = 0; slock_lock(adapter->send_control_lock); if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size)) { fifo_read(adapter->send_control_buffer, &send_command_size, sizeof(send_command_size)); if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size)) { fifo_read(adapter->send_control_buffer, send_command_buf, send_command_size); libusb_interrupt_transfer(adapter->handle, adapter->endpoint_out, send_command_buf, send_command_size, &tmp, 1000); } } slock_unlock(adapter->send_control_lock); libusb_interrupt_transfer(adapter->handle, adapter->endpoint_in, &adapter->data[1], adapter->endpoint_in_max_size, &size, 1000); if (adapter && hid && hid->slots && size) pad_connection_packet(&hid->slots[adapter->slot], adapter->slot, adapter->data, size+1); } }
static void autosave_thread(void *data) { autosave_t *save = (autosave_t*)data; bool first_log = true; while (!save->quit) { autosave_lock(save); bool differ = memcmp(save->buffer, save->retro_buffer, save->bufsize) != 0; if (differ) memcpy(save->buffer, save->retro_buffer, save->bufsize); autosave_unlock(save); if (differ) { // Should probably deal with this more elegantly. FILE *file = fopen(save->path, "wb"); if (file) { // Avoid spamming down stderr ... :) if (first_log) { RARCH_LOG("Autosaving SRAM to \"%s\", will continue to check every %u seconds ...\n", save->path, save->interval); first_log = false; } else RARCH_LOG("SRAM changed ... autosaving ...\n"); bool failed = false; failed |= fwrite(save->buffer, 1, save->bufsize, file) != save->bufsize; failed |= fflush(file) != 0; failed |= fclose(file) != 0; if (failed) RARCH_WARN("Failed to autosave SRAM. Disk might be full.\n"); } } slock_lock(save->cond_lock); if (!save->quit) scond_wait_timeout(save->cond, save->cond_lock, save->interval * 1000); slock_unlock(save->cond_lock); } }
static bool video_thread_alive(void *data) { bool ret; thread_video_t *thr = (thread_video_t*)data; if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL)) { thread_packet_t pkt = { CMD_ALIVE }; video_thread_send_and_wait_user_to_thread(thr, &pkt); return pkt.data.b; } slock_lock(thr->lock); ret = thr->alive; slock_unlock(thr->lock); return ret; }
static bool retro_task_threaded_find( retro_task_finder_t func, void *user_data) { retro_task_t *task = NULL; bool result = false; slock_lock(running_lock); for (task = tasks_running.front; task; task = task->next) { if (func(task, user_data)) { result = true; break; } } slock_unlock(running_lock); return result; }
static void audio_thread_block(audio_thread_t *thr) { if (!thr) return; if (thr->stopped) return; slock_lock(thr->lock); thr->stopped_ack = false; thr->stopped = true; scond_signal(thr->cond); /* Wait until audio driver actually goes to sleep. */ while (!thr->stopped_ack) scond_wait(thr->cond, thr->lock); slock_unlock(thr->lock); }
/** * rarch_threaded_audio_init: * @out_driver : output driver * @out_data : output audio data * @device : audio device (optional) * @out_rate : output audio rate * @latency : audio latency * @driver : audio driver * * Starts a audio driver in a new thread. * Access to audio driver will be mediated through this driver. * This driver interfaces with audio callback and is * only used in that case. * * Returns: true (1) if successful, otherwise false (0). **/ bool rarch_threaded_audio_init(const audio_driver_t **out_driver, void **out_data, const char *device, unsigned audio_out_rate, unsigned latency, const audio_driver_t *drv) { audio_thread_t *thr = (audio_thread_t*)calloc(1, sizeof(*thr)); if (!thr) return false; thr->driver = (const audio_driver_t*)drv; thr->device = device; thr->out_rate = audio_out_rate; thr->latency = latency; if (!(thr->cond = scond_new())) goto error; if (!(thr->lock = slock_new())) goto error; thr->alive = true; thr->stopped = true; if (!(thr->thread = sthread_create(audio_thread_loop, thr))) goto error; /* Wait until thread has initialized (or failed) the driver. */ slock_lock(thr->lock); while (!thr->inited) scond_wait(thr->cond, thr->lock); slock_unlock(thr->lock); if (thr->inited < 0) /* Thread failed. */ goto error; *out_driver = &audio_thread; *out_data = thr; return true; error: *out_driver = NULL; *out_data = NULL; audio_thread_free(thr); return false; }
static void deinit_thread(ffemu_t *handle) { if (handle->thread) { slock_lock(handle->cond_lock); handle->alive = false; handle->can_sleep = false; slock_unlock(handle->cond_lock); scond_signal(handle->cond); sthread_join(handle->thread); slock_free(handle->lock); slock_free(handle->cond_lock); scond_free(handle->cond); handle->thread = NULL; } }