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); slock_free(runloop->overlay_lock); scond_free(runloop->cond); } }
void Task::Impl::execute(const TWork &work, void *param) { slock_lock(this->mutex); if (work == NULL || !this->_isThreadRunning) { slock_unlock(this->mutex); return; } this->workFunc = work; this->workFuncParam = param; scond_signal(this->condWork); slock_unlock(this->mutex); }
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"); }
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 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 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; } }
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; }
void Task::Impl::start(bool spinlock) { slock_lock(this->mutex); if (this->_isThreadRunning) { slock_unlock(this->mutex); return; } this->workFunc = NULL; this->workFuncParam = NULL; this->ret = NULL; this->exitThread = false; this->_thread = (sthread_t*)sthread_create(&taskProc, this); this->_isThreadRunning = true; slock_unlock(this->mutex); }
/** * autosave_free: * @handle : pointer to autosave object * * Frees autosave object. **/ void autosave_free(autosave_t *handle) { if (!handle) return; 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 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; }
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 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 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 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; } }
/** * 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 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); }
void tactx_Recycle(TA_context* poped_ctx) { #ifndef TARGET_NO_THREADS slock_lock(mtx_pool); #endif if (ctx_pool.size()>2) { poped_ctx->Free(); delete poped_ctx; } else { poped_ctx->Reset(); ctx_pool.push_back(poped_ctx); } #ifndef TARGET_NO_THREADS slock_unlock(mtx_pool); #endif }
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 ssize_t sdl_audio_write(void *data, const void *buf, size_t size) { sdl_audio_t *sdl = (sdl_audio_t*)data; ssize_t ret = 0; if (sdl->nonblock) { SDL_LockAudio(); size_t avail = fifo_write_avail(sdl->buffer); size_t write_amt = avail > size ? size : avail; fifo_write(sdl->buffer, buf, write_amt); SDL_UnlockAudio(); ret = write_amt; } else { size_t written = 0; while (written < size) { SDL_LockAudio(); size_t avail = fifo_write_avail(sdl->buffer); if (avail == 0) { SDL_UnlockAudio(); slock_lock(sdl->lock); scond_wait(sdl->cond, sdl->lock); slock_unlock(sdl->lock); } else { size_t write_amt = size - written > avail ? avail : size - written; fifo_write(sdl->buffer, (const char*)buf + written, write_amt); SDL_UnlockAudio(); written += write_amt; } } ret = written; } return ret; }
static OSStatus audio_write_cb(void *userdata, AudioUnitRenderActionFlags *action_flags, const AudioTimeStamp *time_stamp, UInt32 bus_number, UInt32 number_frames, AudioBufferList *io_data) { void *outbuf; unsigned write_avail; coreaudio_t *dev = (coreaudio_t*)userdata; (void)time_stamp; (void)bus_number; (void)number_frames; if (!io_data) return noErr; if (io_data->mNumberBuffers != 1) return noErr; write_avail = io_data->mBuffers[0].mDataByteSize; outbuf = io_data->mBuffers[0].mData; slock_lock(dev->lock); if (fifo_read_avail(dev->buffer) < write_avail) { *action_flags = kAudioUnitRenderAction_OutputIsSilence; /* Seems to be needed. */ memset(outbuf, 0, write_avail); slock_unlock(dev->lock); /* Technically possible to deadlock without. */ scond_signal(dev->cond); return noErr; } fifo_read(dev->buffer, outbuf, write_avail); slock_unlock(dev->lock); scond_signal(dev->cond); return noErr; }
void ssem_wait(ssem_t *semaphore) { if (!semaphore) return; slock_lock(semaphore->mutex); semaphore->value--; if (semaphore->value < 0) { do { scond_wait(semaphore->cond, semaphore->mutex); }while (semaphore->wakeups < 1); semaphore->wakeups--; } slock_unlock(semaphore->mutex); }
static ssize_t audio_thread_write(void *data, const void *buf, size_t size) { ssize_t ret; audio_thread_t *thr = (audio_thread_t*)data; if (!thr) return 0; ret = thr->driver->write(thr->driver_data, buf, size); if (ret < 0) { slock_lock(thr->lock); thr->alive = false; scond_signal(thr->cond); slock_unlock(thr->lock); } return ret; }
void* Task::Impl::finish() { void *returnValue = NULL; slock_lock(this->mutex); if (!this->_isThreadRunning) { slock_unlock(this->mutex); return returnValue; } while (this->workFunc != NULL) scond_wait(this->condWork, this->mutex); returnValue = this->ret; slock_unlock(this->mutex); return returnValue; }
static ssize_t coreaudio_write(void *data, const void *buf_, size_t size, bool is_perfcnt_enable) { coreaudio_t *dev = (coreaudio_t*)data; const uint8_t *buf = (const uint8_t*)buf_; size_t written = 0; while (!g_interrupted && size > 0) { size_t write_avail; slock_lock(dev->lock); write_avail = fifo_write_avail(dev->buffer); if (write_avail > size) write_avail = size; fifo_write(dev->buffer, buf, write_avail); buf += write_avail; written += write_avail; size -= write_avail; if (dev->nonblock) { slock_unlock(dev->lock); break; } #if TARGET_OS_IPHONE if (write_avail == 0 && !scond_wait_timeout( dev->cond, dev->lock, 3000000)) g_interrupted = true; #else if (write_avail == 0) scond_wait(dev->cond, dev->lock); #endif slock_unlock(dev->lock); } return written; }
static void libusb_hid_device_send_control(void *data, uint8_t* data_buf, size_t size) { struct libusb_adapter *adapter = (struct libusb_adapter*)data; if (!adapter) return; slock_lock(adapter->send_control_lock); if (fifo_write_avail(adapter->send_control_buffer) >= size + sizeof(size)) { fifo_write(adapter->send_control_buffer, &size, sizeof(size)); fifo_write(adapter->send_control_buffer, data_buf, size); } else { RARCH_WARN("adapter write buffer is full, cannot write send control\n"); } slock_unlock(adapter->send_control_lock); }