/** * g_cond_timed_wait: * @cond: a #GCond * @mutex: a #GMutex that is currently locked * @abs_time: a #GTimeVal, determining the final time * * Waits until this thread is woken up on @cond, but not longer than * until the time specified by @abs_time. The @mutex is unlocked before * falling asleep and locked again before resuming. * * If @abs_time is %NULL, g_cond_timed_wait() acts like g_cond_wait(). * * This function can be used even if g_thread_init() has not yet been * called, and, in that case, will immediately return %TRUE. * * To easily calculate @abs_time a combination of g_get_current_time() * and g_time_val_add() can be used. * * Returns: %TRUE if @cond was signalled, or %FALSE on timeout * * Deprecated:2.32: Use g_cond_wait_until() instead. */ gboolean g_cond_timed_wait (GCond *cond, GMutex *mutex, GTimeVal *abs_time) { gint64 end_time; if (abs_time == NULL) { g_cond_wait (cond, mutex); return TRUE; } end_time = abs_time->tv_sec; end_time *= 1000000; end_time += abs_time->tv_usec; #ifdef CLOCK_MONOTONIC /* would be nice if we had clock_rtoffset, but that didn't seem to * make it into the kernel yet... */ end_time += g_get_monotonic_time () - g_get_real_time (); #else /* if CLOCK_MONOTONIC is not defined then g_get_montonic_time() and * g_get_real_time() are returning the same clock, so don't bother... */ #endif return g_cond_wait_until (cond, mutex, end_time); }
static gpointer idle_thread (gpointer data) { HTTPServer *http_server = (HTTPServer *)data; ForeachFuncData func_data; GSList *wakeup_list = NULL; func_data.http_server = http_server; func_data.wakeup_list = &wakeup_list; for (;;) { g_mutex_lock (&(http_server->idle_queue_mutex)); while (g_tree_nnodes (http_server->idle_queue) == 0) { g_cond_wait (&(http_server->idle_queue_cond), &(http_server->idle_queue_mutex)); } func_data.wakeup_time = 0; g_tree_foreach (http_server->idle_queue, gtree_foreach_func, &func_data); if (wakeup_list != NULL) { g_slist_foreach (wakeup_list, gslist_foreach_func, http_server); g_slist_free (wakeup_list); wakeup_list = NULL; } if (func_data.wakeup_time != 0) { /* more than one idle request in the idle queue, wait until. */ g_cond_wait_until (&(http_server->idle_queue_cond), &(http_server->idle_queue_mutex), func_data.wakeup_time); } g_mutex_unlock (&(http_server->idle_queue_mutex)); } return NULL; }
OMX_ERRORTYPE gst_omx_buf_tab_wait_free (GstOmxBufTab * buftab) { OMX_ERRORTYPE error; guint64 endtime; g_return_val_if_fail (buftab, OMX_ErrorBadParameter); error = OMX_ErrorNone; endtime = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND; g_mutex_lock (&buftab->tabmutex); /* Wait until all the buffers have return to the mothership */ while (buftab->tabused) if (!g_cond_wait_until (&buftab->tabcond, &buftab->tabmutex, endtime)) goto timeout; g_mutex_unlock (&buftab->tabmutex); return error; timeout: g_print ("Failed %p, tabused %d\n", buftab, buftab->tabused); g_mutex_unlock (&buftab->tabmutex); error = OMX_ErrorTimeout; return error; }
static gpointer g_async_queue_pop_intern_unlocked (GAsyncQueue *queue, gboolean wait, gint64 end_time) { gpointer retval; if (!g_queue_peek_tail_link (&queue->queue) && wait) { queue->waiting_threads++; while (!g_queue_peek_tail_link (&queue->queue)) { if (end_time == -1) g_cond_wait (&queue->cond, &queue->mutex); else { if (!g_cond_wait_until (&queue->cond, &queue->mutex, end_time)) break; } } queue->waiting_threads--; } retval = g_queue_pop_tail (&queue->queue); g_assert (retval || !wait || end_time > 0); return retval; }
OMX_BUFFERHEADERTYPE * gst_omx_buf_queue_pop_buffer (GstOmxBufQueue * bufqueue) { OMX_BUFFERHEADERTYPE *buffer = NULL; guint64 endtime; endtime = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND; g_mutex_lock (&bufqueue->queuemutex); retry: while (g_queue_is_empty (bufqueue->queue)) { if (!g_cond_wait_until (&bufqueue->queuecond, &bufqueue->queuemutex, endtime)) goto timeout; else goto retry; } buffer = (OMX_BUFFERHEADERTYPE *) g_queue_pop_head (bufqueue->queue); g_mutex_unlock (&bufqueue->queuemutex); return buffer; timeout: g_mutex_unlock (&bufqueue->queuemutex); return buffer; }
/** * gst_clock_wait_for_sync: * @clock: a GstClock * @timeout: timeout for waiting or %GST_CLOCK_TIME_NONE * * Waits until @clock is synced for reporting the current time. If @timeout * is %GST_CLOCK_TIME_NONE it will wait forever, otherwise it will time out * after @timeout nanoseconds. * * For asynchronous waiting, the GstClock::synced signal can be used. * * * This returns immediately with TRUE if GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC * is not set on the clock, or if the clock is already synced. * * Returns: %TRUE if waiting was successful, or %FALSE on timeout * * Since: 1.6 */ gboolean gst_clock_wait_for_sync (GstClock * clock, GstClockTime timeout) { gboolean timed_out = FALSE; g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); GST_OBJECT_LOCK (clock); if (!GST_OBJECT_FLAG_IS_SET (clock, GST_CLOCK_FLAG_NEEDS_STARTUP_SYNC) || clock->priv->synced) { GST_OBJECT_UNLOCK (clock); return TRUE; } if (timeout != GST_CLOCK_TIME_NONE) { gint64 end_time = g_get_monotonic_time () + gst_util_uint64_scale (timeout, G_TIME_SPAN_SECOND, GST_SECOND); while (!clock->priv->synced && !timed_out) { timed_out = !g_cond_wait_until (&clock->priv->sync_cond, GST_OBJECT_GET_LOCK (clock), end_time); } } else { timed_out = FALSE; while (!clock->priv->synced) { g_cond_wait (&clock->priv->sync_cond, GST_OBJECT_GET_LOCK (clock)); } } GST_OBJECT_UNLOCK (clock); return !timed_out; }
static gpointer connection_timeout_thread_func(ErDtlsConnection *self) { ErDtlsConnectionPrivate *priv = self->priv; struct timeval timeout; gint64 end_time, wait_time; gint ret; while (priv->is_alive) { LOG_TRACE(self, "locking @ timeout"); g_mutex_lock(&priv->mutex); LOG_TRACE(self, "locked @ timeout"); if (DTLSv1_get_timeout(priv->ssl, &timeout)) { wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec; if (wait_time) { LOG_DEBUG(self, "waiting for %" G_GINT64_FORMAT " usec", wait_time); end_time = g_get_monotonic_time() + wait_time; LOG_TRACE(self, "wait @ timeout"); g_cond_wait_until(&priv->condition, &priv->mutex, end_time); LOG_TRACE(self, "continued @ timeout"); } ret = DTLSv1_handle_timeout(priv->ssl); LOG_DEBUG(self, "handle timeout returned %d, is_alive: %d", ret, priv->is_alive); if (ret < 0) { LOG_TRACE(self, "unlocking @ timeout failed"); g_mutex_unlock(&priv->mutex); break; /* self failed after DTLS1_TMO_ALERT_COUNT (12) attempts */ } if (ret > 0) { log_state(self, "handling timeout before poll"); openssl_poll(self); log_state(self, "handling timeout after poll"); } } else { LOG_DEBUG(self, "waiting indefinitely"); priv->timeout_set = FALSE; while (!priv->timeout_set && priv->is_alive) { LOG_TRACE(self, "wait @ timeout"); g_cond_wait(&priv->condition, &priv->mutex); } LOG_TRACE(self, "continued @ timeout"); } LOG_TRACE(self, "unlocking @ timeout"); g_mutex_unlock(&priv->mutex); } log_state(self, "timeout thread exiting"); return NULL; }
static void fetch_items(GTask* task, gpointer source, gpointer task_data, GCancellable* cancel) { g_assert(GT_IS_SEARCH_GAME_CONTAINER(source)); GtSearchGameContainer* self = GT_SEARCH_GAME_CONTAINER(source); GtSearchGameContainerPrivate* priv = gt_search_game_container_get_instance_private(self); g_assert(G_IS_CANCELLABLE(cancel)); g_assert(G_IS_TASK(task)); if (g_task_return_error_if_cancelled(task)) return; if (utils_str_empty(priv->query)) { g_task_return_pointer(task, NULL, NULL); return; } g_assert_nonnull(task_data); FetchItemsData* data = task_data; g_mutex_lock(&priv->mutex); gint64 end_time = g_get_monotonic_time() + SEARCH_DELAY; g_cancellable_connect(cancel, G_CALLBACK(cancelled_cb), self, NULL); while (!g_cancellable_is_cancelled(cancel)) { if (!g_cond_wait_until(&priv->cond, &priv->mutex, end_time)) { /* We weren't cancelled */ g_assert(!utils_str_empty(priv->query)); GError* err = NULL; GList* items = data->offset == 0 ? gt_twitch_search_games(main_app->twitch, priv->query, data->amount, data->offset, &err) : NULL; if (err) g_task_return_error(task, err); else g_task_return_pointer(task, items, (GDestroyNotify) gt_game_list_free); g_mutex_unlock(&priv->mutex); return; } } /* We were cancelled */ g_assert(g_task_return_error_if_cancelled(task)); g_mutex_unlock(&priv->mutex); }
static inline void renderer_wait_until (App * app, GstClockTime pts) { g_mutex_lock (&app->mutex); do { } while (g_cond_wait_until (&app->render_ready, &app->mutex, pts)); g_mutex_unlock (&app->mutex); }
gpointer display_thread(gpointer data) { GCContext *context = (GCContext*)data; GCConfig *config = context->config; GCVDPAUContext *vdpau = &context->VDPAU_context; Movie *movie = context->movie_context; gint64 timeout = 0; int current_direction = DIRECTION_FORWARD; if (!context) g_error("Missing context\n"); movie->pre_load_surface = vdpau->surface_queue.next; load_frame(context, movie->frame_offset, movie->pre_load_surface); do { movie->pre_load_surface = display_surface(context, movie->pre_load_surface); timeout = g_get_monotonic_time() + config->seconds_per_frame * G_TIME_SPAN_SECOND; g_mutex_lock(&movie->tick_lock); if (movie->ease_to) { movie->new_frame = FALSE; easeout_to_frame(context, movie->ease_to_frame, config->easing_factor); movie->ease_to = FALSE; } while (!movie->new_frame && !movie->ease_to && !context->exit) { if (!g_cond_wait_until(&movie->tick_cond, &movie->tick_lock, timeout)) { movie->frame_offset++; movie->fract_frame_count++; movie->play_direction = DIRECTION_FORWARD; movie->new_frame = TRUE; //g_message("tick: %lu", movie->frame_offset); break; } } movie->new_frame = FALSE; g_mutex_unlock(&movie->tick_lock); load_frame(context, movie->frame_offset, movie->pre_load_surface); } while (!context->exit); munmap(movie->planes, config->movie_size); close(movie->fd_movie); vdpau_exit(context); x11_exit(context); g_main_loop_quit(context->g_main_loop); return NULL; }
static gboolean _cond_wait_until(GCond *cond, GMutex *mutex, gint64 end_time) { gboolean ret = FALSE; #ifdef HAVE_COND_INIT ret = g_cond_wait_until(cond, mutex, end_time); #else GTimeVal time = { end_time / G_TIME_SPAN_SECOND, end_time % G_TIME_SPAN_SECOND }; ret = g_cond_timed_wait(cond, mutex, &time); #endif return ret; }
static void wait_for_rings_started(TestServer *s, size_t count) { gint64 end_time; g_mutex_lock(&s->data_mutex); end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; while (ctpop64(s->rings) != count) { if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { /* timeout has passed */ g_assert_cmpint(ctpop64(s->rings), ==, count); break; } }
/* Wait until cond is signalled, or timeout us have passed. * * You can get spurious wakeups, use this in a loop. */ void vips_g_cond_timed_wait( GCond *cond, GMutex *mutex, gint64 timeout ) { #ifdef HAVE_COND_INIT g_cond_wait_until( cond, mutex, g_get_monotonic_time() + timeout ); #else GTimeVal time; g_get_current_time( &time ); g_time_val_add( &time, timeout ); g_cond_timed_wait( cond, mutex, &time ); #endif }
static gpointer block_thread (gpointer data) { HTTPServer *http_server = (HTTPServer *)data; gint64 wakeup_time; for (;;) { g_mutex_lock (&(http_server->block_queue_mutex)); wakeup_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND; g_cond_wait_until (&(http_server->block_queue_cond), &(http_server->block_queue_mutex), wakeup_time); g_queue_foreach (http_server->block_queue, block_queue_foreach_func, http_server); g_mutex_unlock (&(http_server->block_queue_mutex)); } return NULL; }
/* returns FALSE if cancelled, in which case the lock is not held */ gboolean e_mapi_cancellable_rec_mutex_lock (EMapiCancellableRecMutex *rec_mutex, GCancellable *cancellable, GError **error) { gulong handler_id; gboolean res = TRUE; g_return_val_if_fail (rec_mutex != NULL, FALSE); g_mutex_lock (&rec_mutex->cond_mutex); if (!cancellable) { g_mutex_unlock (&rec_mutex->cond_mutex); g_rec_mutex_lock (&rec_mutex->rec_mutex); return TRUE; } if (g_cancellable_is_cancelled (cancellable)) { if (error && !*error) { /* coverity[unchecked_value] */ g_cancellable_set_error_if_cancelled (cancellable, error); } g_mutex_unlock (&rec_mutex->cond_mutex); return FALSE; } handler_id = g_signal_connect (cancellable, "cancelled", G_CALLBACK (cancellable_rec_mutex_cancelled_cb), rec_mutex); while (!g_rec_mutex_trylock (&rec_mutex->rec_mutex)) { /* recheck once per 10 seconds, just in case */ g_cond_wait_until (&rec_mutex->cond, &rec_mutex->cond_mutex, g_get_monotonic_time () + (10 * G_TIME_SPAN_SECOND)); if (g_cancellable_is_cancelled (cancellable)) { if (error && !*error) g_cancellable_set_error_if_cancelled (cancellable, error); res = FALSE; break; } } g_signal_handler_disconnect (cancellable, handler_id); g_mutex_unlock (&rec_mutex->cond_mutex); return res; }
OMX_ERRORTYPE gst_omx_buf_tab_get_free_buffer (GstOmxBufTab * buftab, OMX_BUFFERHEADERTYPE ** buffer) { OMX_ERRORTYPE error; GList *table; GstOmxBufTabNode *node; guint64 endtime; g_return_val_if_fail (buftab, OMX_ErrorBadParameter); error = OMX_ErrorNone; table = buftab->table; endtime = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND; *buffer = NULL; g_mutex_lock (&buftab->tabmutex); retry: table = buftab->table; while (table) { node = (GstOmxBufTabNode *) table->data; if (!node->busy) { *buffer = node->buffer; break; } table = g_list_next (table); } while (!*buffer) { if (!g_cond_wait_until (&buftab->tabcond, &buftab->tabmutex, endtime)) goto timeout; else goto retry; } g_mutex_unlock (&buftab->tabmutex); return error; timeout: g_mutex_unlock (&buftab->tabmutex); error = OMX_ErrorTimeout; return error; }
static void wait_for_log_fd(TestServer *s) { gint64 end_time; g_mutex_lock(&s->data_mutex); end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; while (s->log_fd == -1) { if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { /* timeout has passed */ g_assert(s->log_fd != -1); break; } } g_mutex_unlock(&s->data_mutex); }
void delay_usec(unsigned int usec) { GMutex mutex; GCond cond; gint64 timeout; g_mutex_init(&mutex); g_cond_init(&cond); timeout = g_get_monotonic_time() + usec; g_mutex_lock(&mutex); while (g_cond_wait_until(&cond, &mutex, timeout)) ; g_mutex_unlock(&mutex); g_mutex_clear(&mutex); g_cond_clear(&cond); }
OMX_ERRORTYPE gst_omx_buf_tab_remove_buffer (GstOmxBufTab * buftab, OMX_BUFFERHEADERTYPE * buffer) { OMX_ERRORTYPE error; GList *toremove; guint64 endtime; GstOmxBufTabNode *node; g_return_val_if_fail (buftab, OMX_ErrorBadParameter); g_return_val_if_fail (buffer, OMX_ErrorBadParameter); error = OMX_ErrorNone; toremove = NULL; g_mutex_lock (&buftab->tabmutex); endtime = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND; toremove = g_list_find_custom (buftab->table, (gconstpointer) buffer, (GCompareFunc) gst_omx_buf_tab_compare); if (!toremove) goto notfound; node = (GstOmxBufTabNode *) toremove->data; while (node->busy) if (!g_cond_wait_until (&buftab->tabcond, &buftab->tabmutex, endtime)) goto timeout; buftab->table = g_list_remove (buftab->table, (gpointer) toremove->data); g_free(node); g_mutex_unlock (&buftab->tabmutex); return error; notfound: g_mutex_unlock (&buftab->tabmutex); error = OMX_ErrorResourcesLost; return error; timeout: g_mutex_unlock (&buftab->tabmutex); error = OMX_ErrorTimeout; return error; }
bool Wait(uint32_t timeout_ms) { gint64 endTime; g_mutex_lock(&m_mutex); endTime = g_get_monotonic_time() + timeout_ms * G_TIME_SPAN_MILLISECOND; while (!m_isResolved) { if (!g_cond_wait_until(&m_cond, &m_mutex, endTime)) { g_mutex_unlock(&m_mutex); return false; } } g_mutex_unlock(&m_mutex); return true; }
/** * e_cancellable_mutex_lock: * @mutex: an #ECancellableMutex instance * @cancellable: (allow-none): a #GCancellable, or %NULL * * Acquires lock on @mutex. The returned value indicates whether * the lock was acquired, while %FALSE is returned only either or * invalid arguments or the passed in @cancellable had been cancelled. * In case of %NULL @cancellable the function blocks like g_mutex_lock(). * * Returns: %TRUE, if lock had been acquired, %FALSE otherwise * * Since: 3.8 **/ gboolean e_cancellable_mutex_lock (ECancellableMutex *mutex, GCancellable *cancellable) { gulong handler_id; gboolean res = TRUE; g_return_val_if_fail (mutex != NULL, FALSE); g_mutex_lock (&mutex->base.cond_mutex); if (!cancellable) { g_mutex_unlock (&mutex->base.cond_mutex); g_mutex_lock (&mutex->mutex); return TRUE; } if (g_cancellable_is_cancelled (cancellable)) { g_mutex_unlock (&mutex->base.cond_mutex); return FALSE; } handler_id = g_signal_connect ( cancellable, "cancelled", G_CALLBACK (cancellable_locks_cancelled_cb), &mutex->base); while (!g_mutex_trylock (&mutex->mutex)) { /* recheck once per 10 seconds, just in case */ g_cond_wait_until ( &mutex->base.cond, &mutex->base.cond_mutex, g_get_monotonic_time () + (10 * G_TIME_SPAN_SECOND)); if (g_cancellable_is_cancelled (cancellable)) { res = FALSE; break; } } g_signal_handler_disconnect (cancellable, handler_id); g_mutex_unlock (&mutex->base.cond_mutex); return res; }
static gboolean idle_start_test1_thread (gpointer use_thread_context) { guint64 time; GThread *thread; g_mutex_lock (&test1_mutex); thread = g_thread_new ("test1_thread", test1_thread, use_thread_context); time = g_get_monotonic_time () + 5000000; if (g_cond_wait_until (&test1_cond, &test1_mutex, time)) g_thread_join (thread); else { soup_test_assert (FALSE, "timeout"); g_thread_unref (thread); } g_mutex_unlock (&test1_mutex); g_main_loop_quit (test1_loop); return FALSE; }
static void wait_for_fds(TestServer *s) { gint64 end_time; g_mutex_lock(&s->data_mutex); end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; while (!s->fds_num) { if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { /* timeout has passed */ g_assert(s->fds_num); break; } } /* check for sanity */ g_assert_cmpint(s->fds_num, >, 0); g_assert_cmpint(s->fds_num, ==, s->memory.nregions); g_mutex_unlock(&s->data_mutex); }
int fs_condition_wait_until(fs_condition *condition, fs_mutex *mutex, int64_t end_time) { #if defined(USE_PTHREADS) struct timespec tv; tv.tv_sec = end_time / 1000000; tv.tv_nsec = (end_time % 1000000) * 1000; return pthread_cond_timedwait(&condition->condition, &mutex->mutex, &tv); #elif defined(USE_GLIB) // GTimeVal tv; // tv.tv_sec = end_time / 1000000; // tv.tv_usec = end_time % 1000000; // gboolean result = g_cond_timed_wait( // &condition->condition, &mutex->mutex, &tv); gboolean result = g_cond_wait_until( &condition->condition, &mutex->mutex, end_time); return !result; #elif defined(USE_SDL) // FIXME: no timed wait... return SDL_CondWait(condition->condition, mutex->mutex); #else #error no thread support #endif }
static void WaitForManualEvent(ManualEvent ME) { #if GLIB_CHECK_VERSION (2,32,0) gint64 end_time; #else GTimeVal tv; #endif multi_debug("wait for manual event locks"); #if GLIB_CHECK_VERSION (2,32,0) g_mutex_lock(&condMutex); end_time = g_get_monotonic_time() + 10 * G_TIME_SPAN_SECOND; #else g_mutex_lock(condMutex); #endif while (!ME->signalled) { multi_debug("waiting for manual event"); #if GLIB_CHECK_VERSION (2,32,0) if (!g_cond_wait_until(&ME->cond, &condMutex, end_time)) #else g_get_current_time(&tv); g_time_val_add(&tv, 10 * 1000 * 1000); if (g_cond_timed_wait(ME->cond, condMutex, &tv)) #endif break; else { multi_debug("still waiting for manual event"); } } #if GLIB_CHECK_VERSION (2,32,0) g_mutex_unlock(&condMutex); #else g_mutex_unlock(condMutex); #endif multi_debug("wait for manual event unlocks"); }
/*! \brief Disables the serial connection and shuts down the reader thread */ G_MODULE_EXPORT void libreems_serial_disable(void) { GIOChannel *channel = NULL; GAsyncQueue *queue = NULL; Serial_Params *serial_params = NULL; GMutex mutex; GCond *cond = NULL; GThread *thread = NULL; gboolean res = FALSE; gint tmpi = 0; ENTER(); g_mutex_init(&mutex); DATA_SET(global_data,"serial_abort",GINT_TO_POINTER(TRUE)); thread = (GThread *)DATA_GET(global_data,"serial_thread_id"); g_mutex_lock(&mutex); /* Wait up to 0.25 seconds for thread to exit */ cond = (GCond *)DATA_GET(global_data,"serial_reader_cond"); g_return_if_fail(cond); if ((cond) && (thread)) { res = g_cond_wait_until(cond,&mutex,g_get_monotonic_time() + 250 * G_TIME_SPAN_MILLISECOND); g_thread_join(thread); } DATA_SET(global_data,"serial_thread_id",NULL); /* if (res) printf("condition signaled\n"); else printf("cond timeout\n"); */ g_mutex_unlock(&mutex); g_mutex_clear(&mutex); EXIT(); return; }
int main(int argc, char **argv) { GThread *thread; gint64 end_time; gegl_init (&argc, &argv); thread = g_thread_new (NULL, test, NULL); end_time = g_get_monotonic_time () + TIMEOUT; g_mutex_lock (&mutex); while (! finished) { if (! g_cond_wait_until (&cond, &mutex, end_time)) break; } g_mutex_unlock (&mutex); if (finished) { g_thread_join (thread); gegl_exit (); return SUCCESS; } else { g_print ("timeout expired. failing.\n"); return FAILURE; } }
static bool wait_for_fds(TestServer *s) { gint64 end_time; bool got_region; int i; g_mutex_lock(&s->data_mutex); end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; while (!s->fds_num) { if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { /* timeout has passed */ g_assert(s->fds_num); break; } } /* check for sanity */ g_assert_cmpint(s->fds_num, >, 0); g_assert_cmpint(s->fds_num, ==, s->memory.nregions); g_mutex_unlock(&s->data_mutex); got_region = false; for (i = 0; i < s->memory.nregions; ++i) { VhostUserMemoryRegion *reg = &s->memory.regions[i]; if (reg->guest_phys_addr == 0) { got_region = true; break; } } if (!got_region) { g_test_skip("No memory at address 0x0"); } return got_region; }
/** @brief RmMDSDevice worker thread **/ static void rm_mds_factory(RmMDSDevice *device, RmMDS *mds) { /* rm_mds_factory processes tasks from device->task_list. * After completing one pass of the device, returns self to the * mds->pool threadpool. */ gint processed = 0; g_mutex_lock(&device->lock); { /* check for empty queues - if so then wait a little while before giving up */ if(!device->sorted_tasks && !device->unsorted_tasks && device->ref_count > 0) { /* timed wait for signal from rm_mds_push_task_impl() */ gint64 end_time = g_get_monotonic_time() + MDS_EMPTYQUEUE_SLEEP_US; g_cond_wait_until(&device->cond, &device->lock, end_time); } /* sort and merge task lists */ if(device->unsorted_tasks) { if(mds->prioritiser) { device->sorted_tasks = g_slist_concat( g_slist_sort_with_data(device->unsorted_tasks, (GCompareDataFunc)rm_mds_compare, (RmMDSSortFunc)mds->prioritiser), device->sorted_tasks); } else { device->sorted_tasks = g_slist_concat(device->unsorted_tasks, device->sorted_tasks); } device->unsorted_tasks = NULL; } } g_mutex_unlock(&device->lock); /* process tasks from device->sorted_tasks */ RmMDSTask *task = NULL; while(processed < mds->pass_quota && (task = rm_util_slist_pop(&device->sorted_tasks, &device->lock))) { if(mds->func(task->task_data, mds->user_data)) { /* task succeeded; update counters */ ++processed; } rm_mds_task_free(task); } if(rm_mds_device_ref(device, 0) > 0) { /* return self to pool for further processing */ if(processed == 0) { /* stalled queue; chill for a bit */ g_usleep(1000); } rm_util_thread_pool_push(mds->pool, device); } else if(g_atomic_int_dec_and_test(&device->threads)) { /* free self and signal to rm_mds_free() */ g_mutex_lock(&mds->lock); { rm_log_debug_line("Freeing device %" LLU " (pointer %p)", (RmOff)device->disk, device); g_hash_table_remove(mds->disks, GINT_TO_POINTER(device->disk)); rm_mds_device_free(device); g_cond_signal(&mds->cond); } g_mutex_unlock(&mds->lock); } }
static gpointer decoder_thread (gpointer data) { App *const app = data; GError *error = NULL; GstVaapiDecoderStatus status; GstVaapiSurfaceProxy *proxy; RenderFrame *rfp; GstBuffer *buffer; GstClockTime pts; gboolean got_surface, got_eos = FALSE; gint64 end_time; guint ofs; g_print ("Decoder thread started\n"); #define SEND_ERROR(...) \ do { \ error = g_error_new(APP_ERROR, APP_ERROR_DECODER, __VA_ARGS__); \ goto send_error; \ } while (0) pts = g_get_monotonic_time (); ofs = 0; while (!app->decoder_thread_cancel) { if (G_UNLIKELY (ofs == app->file_size)) buffer = NULL; else { const gsize size = MIN (4096, app->file_size - ofs); buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, app->file_data, app->file_size, ofs, size, NULL, NULL); if (!buffer) SEND_ERROR ("failed to allocate new buffer"); ofs += size; } if (!gst_vaapi_decoder_put_buffer (app->decoder, buffer)) SEND_ERROR ("failed to push buffer to decoder"); gst_buffer_replace (&buffer, NULL); get_surface: status = gst_vaapi_decoder_get_surface (app->decoder, &proxy); switch (status) { case GST_VAAPI_DECODER_STATUS_SUCCESS: gst_vaapi_surface_proxy_set_destroy_notify (proxy, (GDestroyNotify) decoder_release, app); rfp = render_frame_new (); if (!rfp) SEND_ERROR ("failed to allocate render frame"); rfp->proxy = proxy; rfp->pts = pts; rfp->duration = app->frame_duration; pts += app->frame_duration; g_async_queue_push (app->decoder_queue, rfp); break; case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA: /* nothing to do, just continue to the next iteration */ break; case GST_VAAPI_DECODER_STATUS_END_OF_STREAM: gst_vaapi_decoder_flush (app->decoder); if (got_eos) goto send_eos; got_eos = TRUE; break; case GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE: end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND; g_mutex_lock (&app->mutex); got_surface = g_cond_wait_until (&app->decoder_ready, &app->mutex, end_time); g_mutex_unlock (&app->mutex); if (got_surface) goto get_surface; SEND_ERROR ("failed to acquire a surface within one second"); break; default: SEND_ERROR ("%s", get_decoder_status_string (status)); break; } } return NULL; #undef SEND_ERROR send_eos: app_send_eos (app); return NULL; send_error: app_send_error (app, error); return NULL; }