static gpointer g_thread_pool_wait_for_new_task (GRealThreadPool *pool) { gpointer task = NULL; if (pool->running || (!pool->immediate && g_async_queue_length_unlocked (pool->queue) > 0)) { /* This thread pool is still active. */ if (pool->num_threads > pool->max_threads && pool->max_threads != -1) { /* This is a superfluous thread, so it goes to the global pool. */ DEBUG_MSG (("superfluous thread %p in pool %p.", g_thread_self (), pool)); } else if (pool->pool.exclusive) { /* Exclusive threads stay attached to the pool. */ task = g_async_queue_pop_unlocked (pool->queue); DEBUG_MSG (("thread %p in exclusive pool %p waits for task " "(%d running, %d unprocessed).", g_thread_self (), pool, pool->num_threads, g_async_queue_length_unlocked (pool->queue))); } else { /* A thread will wait for new tasks for at most 1/2 * second before going to the global pool. */ GTimeVal end_time; g_get_current_time (&end_time); g_time_val_add (&end_time, G_USEC_PER_SEC / 2); /* 1/2 second */ DEBUG_MSG (("thread %p in pool %p waits for up to a 1/2 second for task " "(%d running, %d unprocessed).", g_thread_self (), pool, pool->num_threads, g_async_queue_length_unlocked (pool->queue))); task = g_async_queue_timed_pop_unlocked (pool->queue, &end_time); } } else { /* This thread pool is inactive, it will no longer process tasks. */ DEBUG_MSG (("pool %p not active, thread %p will go to global pool " "(running: %s, immediate: %s, len: %d).", pool, g_thread_self (), pool->running ? "true" : "false", pool->immediate ? "true" : "false", g_async_queue_length_unlocked (pool->queue))); } return task; }
static void player_av_set_position (Player *self, guint pos) { PlayerAVPrivate *priv = PLAYER_AV (self)->priv; int stream = priv->astream; int64_t seek_target = av_rescale_q (AV_TIME_BASE * pos, AV_TIME_BASE_Q, priv->fctx->streams[stream]->time_base); if (!av_seek_frame (priv->fctx, stream, seek_target, 0)) { g_print ("It Failed\n"); } else { g_print ("Seek OK?\n"); } g_mutex_lock (priv->rp_mutex); g_async_queue_lock (priv->apq); g_async_queue_lock (priv->vpq); while (g_async_queue_length_unlocked (priv->apq) > 0) { AVPacket *packet = g_async_queue_pop_unlocked (priv->apq); av_free_packet (packet); av_free (packet); } while (g_async_queue_length_unlocked (priv->vpq) > 0) { AVPacket *packet = g_async_queue_pop_unlocked (priv->vpq); av_free_packet (packet); av_free (packet); } avcodec_flush_buffers (priv->actx); if (priv->vctx) { avcodec_flush_buffers (priv->vctx); } g_async_queue_unlock (priv->apq); g_async_queue_unlock (priv->vpq); g_mutex_unlock (priv->rp_mutex); switch (priv->state) { case PLAYER_STATE_PLAYING: break; case PLAYER_STATE_PAUSED: case PLAYER_STATE_STOPPED: break; default: g_print ("Can not change position in current state\n"); }; // g_signal_emit (self, signal_pos, 0, player_av_get_position (self)); _player_emit_position_changed (PLAYER (self), player_av_get_position (self)); }
/** * g_thread_pool_free: * @pool: a #GThreadPool * @immediate: should @pool shut down immediately? * @wait_: should the function wait for all tasks to be finished? * * Frees all resources allocated for @pool. * * If @immediate is %TRUE, no new task is processed for * @pool. Otherwise @pool is not freed before the last task is * processed. Note however, that no thread of this pool is * interrupted, while processing a task. Instead at least all still * running threads can finish their tasks before the @pool is freed. * * If @wait_ is %TRUE, the functions does not return before all tasks * to be processed (dependent on @immediate, whether all or only the * currently running) are ready. Otherwise the function returns immediately. * * After calling this function @pool must not be used anymore. **/ void g_thread_pool_free (GThreadPool *pool, gboolean immediate, gboolean wait_) { GRealThreadPool *real; real = (GRealThreadPool*) pool; g_return_if_fail (real); g_return_if_fail (real->running); /* If there's no thread allowed here, there is not much sense in * not stopping this pool immediately, when it's not empty */ g_return_if_fail (immediate || real->max_threads != 0 || g_async_queue_length (real->queue) == 0); g_async_queue_lock (real->queue); real->running = FALSE; real->immediate = immediate; real->waiting = wait_; if (wait_) { real->cond = g_cond_new (); while (g_async_queue_length_unlocked (real->queue) != -real->num_threads && !(immediate && real->num_threads == 0)) g_cond_wait (real->cond, _g_async_queue_get_mutex (real->queue)); } if (immediate || g_async_queue_length_unlocked (real->queue) == -real->num_threads) { /* No thread is currently doing something (and nothing is left * to process in the queue) */ if (real->num_threads == 0) { /* No threads left, we clean up */ g_async_queue_unlock (real->queue); g_thread_pool_free_internal (real); return; } g_thread_pool_wakeup_and_stop_all (real); } /* The last thread should cleanup the pool */ real->waiting = FALSE; g_async_queue_unlock (real->queue); }
/* Swallow CLOSE_TOKEN items */ static gpointer handle_close_token_ul (IrisQueue *queue, gpointer item) { gint remaining_items; if (item == NULL) return NULL; /* Filter close tokens. They must be the last items in the queue, so we can * avoid filtering actual queue items that happen to be the same value. */ remaining_items = g_async_queue_length_unlocked (queue->priv->q) + queue->priv->q->waiting_threads; g_warn_if_fail (remaining_items >= queue->priv->close_token_count -1); if ((queue->priv->close_token_count > 0) && remaining_items == queue->priv->close_token_count -1) { g_warn_if_fail (item == CLOSE_TOKEN); queue->priv->close_token_count --; return NULL; } else return item; }
/** * g_thread_pool_push: * @pool: a #GThreadPool * @data: a new task for @pool * @error: return location for error, or %NULL * * Inserts @data into the list of tasks to be executed by @pool. * * When the number of currently running threads is lower than the * maximal allowed number of threads, a new thread is started (or * reused) with the properties given to g_thread_pool_new(). * Otherwise, @data stays in the queue until a thread in this pool * finishes its previous task and processes @data. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when a new thread couldn't be * created. In that case @data is simply appended to the queue of * work to do. * * Before version 2.32, this function did not return a success status. * * Returns: %TRUE on success, %FALSE if an error occurred */ gboolean g_thread_pool_push (GThreadPool *pool, gpointer data, GError **error) { GRealThreadPool *real; gboolean result; real = (GRealThreadPool*) pool; g_return_val_if_fail (real, FALSE); g_return_val_if_fail (real->running, FALSE); result = TRUE; g_async_queue_lock (real->queue); if (g_async_queue_length_unlocked (real->queue) >= 0) { /* No thread is waiting in the queue */ GError *local_error = NULL; if (!g_thread_pool_start_thread (real, &local_error)) { g_propagate_error (error, local_error); result = FALSE; } } g_thread_pool_queue_push_unlocked (real, data); g_async_queue_unlock (real->queue); return result; }
void chassis_event_add_with_timeout(chassis *chas, struct event *ev, struct timeval *tv) { chassis_event_op_t *op = chassis_event_op_new(); gssize ret; op->type = CHASSIS_EVENT_OP_ADD; op->ev = ev; chassis_event_op_set_timeout(op, tv); g_async_queue_push_unlocked(chas->event_queue, op); g_debug("%s: cal chassis_event_add_with_timeout, fd:%d, timeout sec:%d,usec:%d", G_STRLOC, chas->event_notify_fds[1], (int) tv->tv_sec, (int) tv->tv_usec); /* ping the event handler */ if (1 != (ret = send(chas->event_notify_fds[1], C("."), 0))) { int last_errno; last_errno = errno; g_debug("%s: cal chassis_event_add_with_timeout, fd:%d errno:%d", G_STRLOC, chas->event_notify_fds[1], last_errno); switch (last_errno) { case EAGAIN: case E_NET_WOULDBLOCK: /* that's fine ... */ g_debug("%s: send() to event-notify-pipe failed: %s (len = %d)", G_STRLOC, g_strerror(errno), g_async_queue_length_unlocked(chas->event_queue)); break; default: g_critical("%s: send() to event-notify-pipe failed: %s (len = %d)", G_STRLOC, g_strerror(errno), g_async_queue_length_unlocked(chas->event_queue)); break; } } }
static gboolean g_thread_pool_start_thread (GRealThreadPool *pool, GError **error) { gboolean success = FALSE; if (pool->num_threads >= pool->max_threads && pool->max_threads != -1) /* Enough threads are already running */ return TRUE; g_async_queue_lock (unused_thread_queue); if (g_async_queue_length_unlocked (unused_thread_queue) < 0) { g_async_queue_push_unlocked (unused_thread_queue, pool); success = TRUE; } g_async_queue_unlock (unused_thread_queue); if (!success) { GThread *thread; /* No thread was found, we have to start a new one */ G_LOCK (threads); while (finished_threads != NULL) { thread = finished_threads->data; finished_threads = g_slist_delete_link (finished_threads, finished_threads); G_UNLOCK (threads); g_thread_join (thread); G_LOCK (threads); } thread = g_thread_try_new ("pool", g_thread_pool_thread_proxy, pool, error); if (thread != NULL) active_threads = g_slist_prepend (active_threads, thread); G_UNLOCK (threads); if (thread == NULL) return FALSE; } /* See comment in g_thread_pool_thread_proxy as to why this is done * here and not there */ pool->num_threads++; return TRUE; }
/** * g_thread_pool_set_max_threads: * @pool: a #GThreadPool * @max_threads: a new maximal number of threads for @pool, * or -1 for unlimited * @error: return location for error, or %NULL * * Sets the maximal allowed number of threads for @pool. * A value of -1 means that the maximal number of threads * is unlimited. If @pool is an exclusive thread pool, setting * the maximal number of threads to -1 is not allowed. * * Setting @max_threads to 0 means stopping all work for @pool. * It is effectively frozen until @max_threads is set to a non-zero * value again. * * A thread is never terminated while calling @func, as supplied by * g_thread_pool_new(). Instead the maximal number of threads only * has effect for the allocation of new threads in g_thread_pool_push(). * A new thread is allocated, whenever the number of currently * running threads in @pool is smaller than the maximal number. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when a new thread couldn't be * created. * * Before version 2.32, this function did not return a success status. * * Returns: %TRUE on success, %FALSE if an error occurred */ gboolean g_thread_pool_set_max_threads (GThreadPool *pool, gint max_threads, GError **error) { GRealThreadPool *real; gint to_start; gboolean result; real = (GRealThreadPool*) pool; g_return_val_if_fail (real, FALSE); g_return_val_if_fail (real->running, FALSE); g_return_val_if_fail (!real->pool.exclusive || max_threads != -1, FALSE); g_return_val_if_fail (max_threads >= -1, FALSE); result = TRUE; g_async_queue_lock (real->queue); real->max_threads = max_threads; if (pool->exclusive) to_start = real->max_threads - real->num_threads; else to_start = g_async_queue_length_unlocked (real->queue); for ( ; to_start > 0; to_start--) { GError *local_error = NULL; if (!g_thread_pool_start_thread (real, &local_error)) { g_propagate_error (error, local_error); result = FALSE; break; } } g_async_queue_unlock (real->queue); return result; }
static gpointer iris_queue_real_timed_pop (IrisQueue *queue, GTimeVal *timeout) { gpointer item; g_async_queue_lock (queue->priv->q); if (g_atomic_int_get (&queue->priv->open) == FALSE && g_async_queue_length_unlocked (queue->priv->q) <= 0) { g_async_queue_unlock (queue->priv->q); return NULL; } item = g_async_queue_timed_pop_unlocked (queue->priv->q, timeout); if (g_atomic_int_get (&queue->priv->open) == FALSE) item = handle_close_token_ul (queue, item); g_async_queue_unlock (queue->priv->q); return item; }
/** * g_thread_pool_push: * @pool: a #GThreadPool * @data: a new task for @pool * @error: return location for error * * Inserts @data into the list of tasks to be executed by @pool. When * the number of currently running threads is lower than the maximal * allowed number of threads, a new thread is started (or reused) with * the properties given to g_thread_pool_new (). Otherwise @data stays * in the queue until a thread in this pool finishes its previous task * and processes @data. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when a new thread couldn't be * created. In that case @data is simply appended to the queue of work * to do. **/ void g_thread_pool_push (GThreadPool *pool, gpointer data, GError **error) { GRealThreadPool *real; real = (GRealThreadPool*) pool; g_return_if_fail (real); g_return_if_fail (real->running); g_async_queue_lock (real->queue); if (g_async_queue_length_unlocked (real->queue) >= 0) /* No thread is waiting in the queue */ g_thread_pool_start_thread (real, error); g_thread_pool_queue_push_unlocked (real, data); g_async_queue_unlock (real->queue); }
static gboolean g_thread_pool_start_thread (GRealThreadPool *pool, GError **error) { gboolean success = FALSE; if (pool->num_threads >= pool->max_threads && pool->max_threads != -1) /* Enough threads are already running */ return TRUE; g_async_queue_lock (unused_thread_queue); if (g_async_queue_length_unlocked (unused_thread_queue) < 0) { g_async_queue_push_unlocked (unused_thread_queue, pool); success = TRUE; } g_async_queue_unlock (unused_thread_queue); if (!success) { GThread *thread; /* No thread was found, we have to start a new one */ thread = g_thread_try_new ("pool", g_thread_pool_thread_proxy, pool, error); if (thread == NULL) return FALSE; g_thread_unref (thread); } /* See comment in g_thread_pool_thread_proxy as to why this is done * here and not there */ pool->num_threads++; return TRUE; }
static void g_thread_pool_start_thread (GRealThreadPool *pool, GError **error) { gboolean success = FALSE; if (pool->num_threads >= pool->max_threads && pool->max_threads != -1) /* Enough threads are already running */ return; g_async_queue_lock (unused_thread_queue); if (g_async_queue_length_unlocked (unused_thread_queue) < 0) { g_async_queue_push_unlocked (unused_thread_queue, pool); success = TRUE; } g_async_queue_unlock (unused_thread_queue); if (!success) { GError *local_error = NULL; /* No thread was found, we have to start a new one */ g_thread_create (g_thread_pool_thread_proxy, pool, FALSE, &local_error); if (local_error) { g_propagate_error (error, local_error); return; } } /* See comment in g_thread_pool_thread_proxy as to why this is done * here and not there */ pool->num_threads++; }
void nids_pcap_handler(u_char * par, struct pcap_pkthdr *hdr, u_char * data) { u_char *data_aligned; #ifdef HAVE_LIBGTHREAD_2_0 struct cap_queue_item *qitem; #endif #ifdef DLT_IEEE802_11 unsigned short fc; int linkoffset_tweaked_by_prism_code = 0; #endif /* * Check for savagely closed TCP connections. Might * happen only when nids_params.tcp_workarounds is non-zero; * otherwise nids_tcp_timeouts is always NULL. */ if (NULL != nids_tcp_timeouts) tcp_check_timeouts(&hdr->ts); nids_last_pcap_header = hdr; nids_last_pcap_data = data; (void)par; /* warnings... */ switch (linktype) { case DLT_EN10MB: if (hdr->caplen < 14) return; /* Only handle IP packets and 802.1Q VLAN tagged packets below. */ if (data[12] == 8 && data[13] == 0) { /* Regular ethernet */ nids_linkoffset = 14; } else if (data[12] == 0x81 && data[13] == 0) { /* Skip 802.1Q VLAN and priority information */ nids_linkoffset = 18; } else /* non-ip frame */ return; break; #ifdef DLT_PRISM_HEADER #ifndef DLT_IEEE802_11 #error DLT_PRISM_HEADER is defined, but DLT_IEEE802_11 is not ??? #endif case DLT_PRISM_HEADER: nids_linkoffset = 144; //sizeof(prism2_hdr); linkoffset_tweaked_by_prism_code = 1; //now let DLT_IEEE802_11 do the rest #endif #ifdef DLT_IEEE802_11 case DLT_IEEE802_11: /* I don't know why frame control is always little endian, but it * works for tcpdump, so who am I to complain? (wam) */ if (!linkoffset_tweaked_by_prism_code) nids_linkoffset = 0; fc = EXTRACT_LE_16BITS(data + nids_linkoffset); if (FC_TYPE(fc) != T_DATA || FC_WEP(fc)) { return; } if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { /* a wireless distribution system packet will have another * MAC addr in the frame */ nids_linkoffset += 30; } else { nids_linkoffset += 24; } if (hdr->len < nids_linkoffset + LLC_FRAME_SIZE) return; if (ETHERTYPE_IP != EXTRACT_16BITS(data + nids_linkoffset + LLC_OFFSET_TO_TYPE_FIELD)) { /* EAP, LEAP, and other 802.11 enhancements can be * encapsulated within a data packet too. Look only at * encapsulated IP packets (Type field of the LLC frame). */ return; } nids_linkoffset += LLC_FRAME_SIZE; break; #endif default:; } if (hdr->caplen < nids_linkoffset) return; /* * sure, memcpy costs. But many EXTRACT_{SHORT, LONG} macros cost, too. * Anyway, libpcap tries to ensure proper layer 3 alignment (look for * handle->offset in pcap sources), so memcpy should not be called. */ #ifdef LBL_ALIGN if ((unsigned long) (data + nids_linkoffset) & 0x3) { data_aligned = alloca(hdr->caplen - nids_linkoffset + 4); data_aligned -= (unsigned long) data_aligned % 4; memcpy(data_aligned, data + nids_linkoffset, hdr->caplen - nids_linkoffset); } else #endif data_aligned = data + nids_linkoffset; #ifdef HAVE_LIBGTHREAD_2_0 if(nids_params.multiproc) { /* * Insert received fragment into the async capture queue. * We hope that the overhead of memcpy * will be saturated by the benefits of SMP - mcree */ qitem=malloc(sizeof(struct cap_queue_item)); if (qitem && (qitem->data=malloc(hdr->caplen - nids_linkoffset))) { qitem->caplen=hdr->caplen - nids_linkoffset; memcpy(qitem->data,data_aligned,qitem->caplen); g_async_queue_lock(cap_queue); /* ensure queue does not overflow */ if(g_async_queue_length_unlocked(cap_queue) > nids_params.queue_limit) { /* queue limit reached: drop packet - should we notify user via syslog? */ free(qitem->data); free(qitem); } else { /* insert packet to queue */ g_async_queue_push_unlocked(cap_queue,qitem); } g_async_queue_unlock(cap_queue); } } else { /* user requested simple passthru - no threading */ call_ip_frag_procs(data_aligned,hdr->caplen - nids_linkoffset, &hdr->ts); } #else call_ip_frag_procs(data_aligned,hdr->caplen - nids_linkoffset, &hdr->ts); #endif }
static gpointer g_thread_pool_thread_proxy (gpointer data) { GRealThreadPool *pool; pool = data; DEBUG_MSG (("thread %p started for pool %p.", g_thread_self (), pool)); g_async_queue_lock (pool->queue); while (TRUE) { gpointer task; task = g_thread_pool_wait_for_new_task (pool); if (task) { if (pool->running || !pool->immediate) { /* A task was received and the thread pool is active, * so execute the function. */ g_async_queue_unlock (pool->queue); DEBUG_MSG (("thread %p in pool %p calling func.", g_thread_self (), pool)); pool->pool.func (task, pool->pool.user_data); g_async_queue_lock (pool->queue); } } else { /* No task was received, so this thread goes to the global pool. */ gboolean free_pool = FALSE; DEBUG_MSG (("thread %p leaving pool %p for global pool.", g_thread_self (), pool)); pool->num_threads--; if (!pool->running) { if (!pool->waiting) { if (pool->num_threads == 0) { /* If the pool is not running and no other * thread is waiting for this thread pool to * finish and this is the last thread of this * pool, free the pool. */ free_pool = TRUE; } else { /* If the pool is not running and no other * thread is waiting for this thread pool to * finish and this is not the last thread of * this pool and there are no tasks left in the * queue, wakeup the remaining threads. */ if (g_async_queue_length_unlocked (pool->queue) == - pool->num_threads) g_thread_pool_wakeup_and_stop_all (pool); } } else if (pool->immediate || g_async_queue_length_unlocked (pool->queue) <= 0) { /* If the pool is not running and another thread is * waiting for this thread pool to finish and there * are either no tasks left or the pool shall stop * immediately, inform the waiting thread of a change * of the thread pool state. */ g_cond_broadcast (&pool->cond); } } g_async_queue_unlock (pool->queue); if (free_pool) g_thread_pool_free_internal (pool); if ((pool = g_thread_pool_wait_for_new_pool ()) == NULL) break; g_async_queue_lock (pool->queue); DEBUG_MSG (("thread %p entering pool %p from global pool.", g_thread_self (), pool)); /* pool->num_threads++ is not done here, but in * g_thread_pool_start_thread to make the new started * thread known to the pool before itself can do it. */ } } return NULL; }