static void *watchdog_thread(void *param) { watchdog *thiz = (watchdog *) param; while (TRUE) { if (osd_event_wait(thiz->event(), thiz->getTimeout())) { if (thiz->do_exit()) break; else { osd_event_reset(thiz->event()); continue; } } else { fprintf(stderr, "Terminating due to watchdog timeout\n"); osd_process_kill(); } } return NULL; }
int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout) { // if we're done already, just return if (item->done) return TRUE; // if we don't have an event, create one if (item->event == NULL) { INT32 lockslot = osd_scalable_lock_acquire(item->queue->lock); item->event = osd_event_alloc(TRUE, FALSE); // manual reset, not signalled osd_scalable_lock_release(item->queue->lock, lockslot); } else osd_event_reset(item->event); // if we don't have an event, we need to spin (shouldn't ever really happen) if (item->event == NULL) { // TODO: do we need to measure the spin time here as well? and how can we do it? spin_while(&item->done, 0, timeout); } // otherwise, block on the event until done else if (!item->done) osd_event_wait(item->event, timeout); // return TRUE if the refcount actually hit 0 return item->done; }
int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout) { // if we're done already, just return if (item->done) return TRUE; // if we don't have an event, create one if (item->event == NULL) item->event = osd_event_alloc(TRUE, FALSE); // manual reset, not signalled else osd_event_reset(item->event); // if we don't have an event, we need to spin (shouldn't ever really happen) if (item->event == NULL) { osd_ticks_t stopspin = osd_ticks() + timeout; do { int spin = 10000; while (--spin && !item->done) osd_yield_processor(); } while (!item->done && osd_ticks() < stopspin); } // otherwise, block on the event until done else if (!item->done) osd_event_wait(item->event, timeout); // return TRUE if the refcount actually hit 0 return item->done; }
static void *worker_thread_entry(void *param) { work_thread_info *thread = (work_thread_info *)param; osd_work_queue *queue = thread->queue; // loop until we exit for ( ;; ) { // block waiting for work or exit // bail on exit, and only wait if there are no pending items in queue if (!queue->exiting && queue->list == NULL) { begin_timing(thread->waittime); osd_event_wait(thread->wakeevent, INFINITE); end_timing(thread->waittime); } if (queue->exiting) break; // indicate that we are live atomic_exchange32(&thread->active, TRUE); atomic_increment32(&queue->livethreads); // process work items for ( ;; ) { osd_ticks_t stopspin; // process as much as we can worker_thread_process(queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL) { // spin for a while looking for more work begin_timing(thread->spintime); stopspin = osd_ticks() + SPIN_LOOP_TIME; do { int spin = 10000; while (--spin && queue->list == NULL) osd_yield_processor(); } while (queue->list == NULL && osd_ticks() < stopspin); end_timing(thread->spintime); } // if nothing more, release the processor if (queue->list == NULL) break; add_to_stat(&queue->spinloops, 1); } // decrement the live thread count atomic_exchange32(&thread->active, FALSE); atomic_decrement32(&queue->livethreads); } return NULL; }
void sdlwindow_video_window_update(running_machine &machine, sdl_window_info *window) { osd_ticks_t event_wait_ticks; ASSERT_MAIN_THREAD(); // adjust the cursor state sdlwindow_update_cursor_state(machine, window); // if we're visible and running and not in the middle of a resize, draw if (window->target != NULL) { int tempwidth, tempheight; // see if the games video mode has changed window->target->compute_minimum_size(tempwidth, tempheight); if (tempwidth != window->minwidth || tempheight != window->minheight) { window->minwidth = tempwidth; window->minheight = tempheight; if (!window->fullscreen) { sdlwindow_blit_surface_size(window, window->width, window->height); sdlwindow_resize(window, window->blitwidth, window->blitheight); } else if (video_config.switchres) { pick_best_mode(window, &tempwidth, &tempheight); sdlwindow_resize(window, tempwidth, tempheight); } } if (video_config.waitvsync && video_config.syncrefresh) event_wait_ticks = osd_ticks_per_second(); // block at most a second else event_wait_ticks = 0; if (osd_event_wait(window->rendered_event, event_wait_ticks)) { worker_param wp; render_primitive_list *primlist; clear_worker_param(&wp); // ensure the target bounds are up-to-date, and then get the primitives primlist = &window->get_primitives(window); // and redraw now wp.list = primlist; wp.window = window; wp.m_machine = &machine; execute_async(&draw_video_contents_wt, &wp); } } }
void sdlwindow_video_window_update(running_machine *machine, sdl_window_info *window) { ASSERT_MAIN_THREAD(); // adjust the cursor state sdlwindow_update_cursor_state(machine, window); // if we're visible and running and not in the middle of a resize, draw if (window->target != NULL) { int tempwidth, tempheight; // see if the games video mode has changed render_target_get_minimum_size(window->target, &tempwidth, &tempheight); if (tempwidth != window->minwidth || tempheight != window->minheight) { window->minwidth = tempwidth; window->minheight = tempheight; if (!window->fullscreen) { sdlwindow_blit_surface_size(window, window->width, window->height); sdlwindow_resize(window, window->blitwidth, window->blitheight); } else if (video_config.switchres) { pick_best_mode(window, &tempwidth, &tempheight); sdlwindow_resize(window, tempwidth, tempheight); } } // only render if we have been signalled if (osd_event_wait(window->rendered_event, 0)) { worker_param wp; const render_primitive_list *primlist; clear_worker_param(&wp); // ensure the target bounds are up-to-date, and then get the primitives primlist = window->get_primitives(window); // and redraw now wp.list = primlist; wp.window = window; wp.machine = machine; execute_async(&draw_video_contents_wt, &wp); } } }
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout) { // if no threads, no waiting if (queue->threads == 0) return TRUE; // if no items, we're done if (queue->items == 0) return TRUE; // if this is a multi queue, help out rather than doing nothing if (queue->flags & WORK_QUEUE_FLAG_MULTI) { work_thread_info *thread = &queue->thread[queue->threads]; end_timing(thread->waittime); // process what we can as a worker thread worker_thread_process(queue, thread); // if we're a high frequency queue, spin until done if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->items != 0) { osd_ticks_t stopspin = osd_ticks() + timeout; // spin until we're done begin_timing(thread->spintime); do { int spin = 10000; while (--spin && queue->items != 0) osd_yield_processor(); } while (queue->items != 0 && osd_ticks() < stopspin); end_timing(thread->spintime); begin_timing(thread->waittime); return (queue->items == 0); } begin_timing(thread->waittime); } // reset our done event and double-check the items before waiting osd_event_reset(queue->doneevent); atomic_exchange32(&queue->waiting, TRUE); if (queue->items != 0) osd_event_wait(queue->doneevent, timeout); atomic_exchange32(&queue->waiting, FALSE); // return TRUE if we actually hit 0 return (queue->items == 0); }
void sdl_window_info::update() { osd_ticks_t event_wait_ticks; ASSERT_MAIN_THREAD(); // adjust the cursor state //sdlwindow_update_cursor_state(machine, window); execute_async(&update_cursor_state_wt, worker_param(this)); // if we're visible and running and not in the middle of a resize, draw if (m_target != NULL) { int tempwidth, tempheight; // see if the games video mode has changed m_target->compute_minimum_size(tempwidth, tempheight); if (osd_dim(tempwidth, tempheight) != m_minimum_dim) { m_minimum_dim = osd_dim(tempwidth, tempheight); if (!this->m_fullscreen) { //Don't resize window without user interaction; //window_resize(blitwidth, blitheight); } else if (video_config.switchres) { osd_dim tmp = this->pick_best_mode(); resize(tmp.width(), tmp.height()); } } if (video_config.waitvsync && video_config.syncrefresh) event_wait_ticks = osd_ticks_per_second(); // block at most a second else event_wait_ticks = 0; if (osd_event_wait(m_rendered_event, event_wait_ticks)) { // ensure the target bounds are up-to-date, and then get the primitives render_primitive_list &primlist = *m_renderer->get_primitives(); // and redraw now execute_async(&draw_video_contents_wt, worker_param(this, primlist)); } } }
static void *worker_thread_entry(void *param) { work_thread_info *thread = (work_thread_info *)param; osd_work_queue *queue = thread->queue; #if defined(SDLMAME_MACOSX) void *arp = NewAutoreleasePool(); #endif // loop until we exit for ( ;; ) { // block waiting for work or exit // bail on exit, and only wait if there are no pending items in queue if (queue->exiting) break; if (!queue_has_list_items(queue)) { begin_timing(thread->waittime); osd_event_wait(thread->wakeevent, OSD_EVENT_WAIT_INFINITE); end_timing(thread->waittime); } if (queue->exiting) break; // indicate that we are live atomic_exchange32(&thread->active, TRUE); atomic_increment32(&queue->livethreads); // process work items for ( ;; ) { // process as much as we can worker_thread_process(queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ && queue->list == NULL) { // spin for a while looking for more work begin_timing(thread->spintime); spin_while(&queue->list, (osd_work_item *)NULL, SPIN_LOOP_TIME); end_timing(thread->spintime); } // if nothing more, release the processor if (!queue_has_list_items(queue)) break; add_to_stat(&queue->spinloops, 1); } // decrement the live thread count atomic_exchange32(&thread->active, FALSE); atomic_decrement32(&queue->livethreads); } #if defined(SDLMAME_MACOSX) ReleaseAutoreleasePool(arp); #endif return NULL; }
void sdl_window_info::update() { osd_ticks_t event_wait_ticks; ASSERT_MAIN_THREAD(); // adjust the cursor state //sdlwindow_update_cursor_state(machine, window); execute_async(&update_cursor_state_wt, worker_param(this)); // if we're visible and running and not in the middle of a resize, draw if (m_target != NULL) { int tempwidth, tempheight; // see if the games video mode has changed m_target->compute_minimum_size(tempwidth, tempheight); if (video_config.switchres && m_fullscreen && machine().options().changeres() && machine().switchres.game.changeres) { switchres_resolution_change(this); return; } else if (osd_dim(tempwidth, tempheight) != m_minimum_dim) { m_minimum_dim = osd_dim(tempwidth, tempheight); if (!this->m_fullscreen) { //Don't resize window without user interaction; //window_resize(blitwidth, blitheight); } else if (video_config.switchres) { osd_dim tmp = this->pick_best_mode(); resize(tmp.width(), tmp.height()); } } int got_lock = false; got_lock = osd_lock_try(m_render_lock); // only render if we were able to get the lock if (got_lock) { // don't hold the lock; we just used it to see if rendering was still happening osd_lock_release(m_render_lock); // ensure the target bounds are up-to-date, and then get the primitives render_primitive_list &primlist = *m_renderer->get_primitives(); // and redraw now osd_event_reset(m_rendered_event); execute_async(&draw_video_contents_wt, worker_param(this, primlist)); if (video_config.waitvsync && machine().video().throttled()) { event_wait_ticks = osd_ticks_per_second(); // block at most a second osd_event_wait(m_rendered_event, event_wait_ticks); } } } }