int input_instance_start_stop_handler(void *priv, struct ptype *run) { struct input *i = priv; char *new_state = PTYPE_BOOL_GETVAL(run); pom_mutex_lock(&i->lock); char cur_state = (i->running == INPUT_RUN_STOPPED ? 0 : 1); if (cur_state == *new_state) { pom_mutex_unlock(&i->lock); pomlog(POMLOG_ERR "Error, input is already %s", (cur_state ? "running" : "stopped")); return POM_ERR; } if (*new_state) { if (!(i->reg->info->flags & INPUT_REG_FLAG_LIVE)) { struct input *tmp; for (tmp = input_head; tmp; tmp = tmp->next) { if (tmp != i) { pom_mutex_lock(&tmp->lock); if (i->running) { pom_mutex_unlock(&tmp->lock); pom_mutex_unlock(&i->lock); pomlog(POMLOG_ERR "When using non-live input, it can only be started alone"); return POM_ERR; } pom_mutex_unlock(&tmp->lock); } } } if (i->reg->info->open && i->reg->info->open(i) != POM_OK) { pomlog(POMLOG_ERR "Error while starting input %s", i->name); pom_mutex_unlock(&i->lock); return POM_ERR; } i->running = INPUT_RUN_RUNNING; pom_mutex_unlock(&i->lock); if (pthread_create(&i->thread, NULL, input_process_thread, (void*) i)) { pom_mutex_unlock(&i->lock); pomlog(POMLOG_ERR "Unable to start a new thread for input %s : %s", i->name, pom_strerror(errno)); return POM_ERR; } input_cur_running++; if (input_cur_running == 1) core_set_state(core_state_running); } else { i->running = INPUT_RUN_STOPPING; pom_mutex_unlock(&i->lock); if (i->reg->info->interrupt && i->reg->info->interrupt(i) == POM_ERR) { pomlog(POMLOG_WARN "Warning : error while interrupting the read process of the input"); } if (i->thread != pthread_self()) { if (pthread_join(i->thread, NULL)) pomlog(POMLOG_WARN "Error while joining the input thread : %s", pom_strerror(errno)); } else { if (pthread_detach(i->thread)) pomlog(POMLOG_WARN "Error while detaching the input thread : %s", pom_strerror(errno)); } input_cur_running--; if (!input_cur_running) core_set_state(core_state_finishing); } return POM_OK; }
void *core_processing_thread_func(void *priv) { struct core_processing_thread *tpriv = priv; if (packet_info_pool_init()) { halt("Error while initializing the packet_info_pool", 1); return NULL; } registry_perf_inc(perf_thread_active, 1); pom_mutex_lock(&tpriv->pkt_queue_lock); while (core_run) { while (!tpriv->pkt_queue_head) { // We are not active while waiting for a packet registry_perf_dec(perf_thread_active, 1); debug_core("thread %u : waiting", tpriv->thread_id); if (registry_perf_getval(perf_thread_active) == 0) { if (core_get_state() == core_state_finishing) core_set_state(core_state_idle); } if (!core_run) { pom_mutex_unlock(&tpriv->pkt_queue_lock); goto end; } int res = pthread_cond_wait(&tpriv->pkt_queue_cond, &tpriv->pkt_queue_lock); if (res) { pomlog(POMLOG_ERR "Error while waiting for restart condition : %s", pom_strerror(res)); abort(); return NULL; } registry_perf_inc(perf_thread_active, 1); } // Dequeue a packet struct core_packet_queue *tmp = tpriv->pkt_queue_head; tpriv->pkt_queue_head = tmp->next; if (!tpriv->pkt_queue_head) tpriv->pkt_queue_tail = NULL; // Add it to the unused list tmp->next = tpriv->pkt_queue_unused; tpriv->pkt_queue_unused = tmp; tpriv->pkt_count--; registry_perf_dec(perf_pkt_queue, 1); __sync_fetch_and_sub(&core_pkt_queue_count, 1); if (tpriv->pkt_count < CORE_THREAD_PKT_QUEUE_MIN) { pom_mutex_lock(&core_pkt_queue_wait_lock); // Tell the input processes that they can continue queuing packets int res = pthread_cond_broadcast(&core_pkt_queue_wait_cond); if (res) { pomlog(POMLOG_ERR "Error while signaling the main pkt_queue condition : %s", pom_strerror(res)); abort(); } pom_mutex_unlock(&core_pkt_queue_wait_lock); } // Keep track of our packet struct packet *pkt = tmp->pkt; debug_core("thread %u : Processing packet %p (%u.%06u)", tpriv->thread_id, pkt, pom_ptime_sec(pkt->ts), pom_ptime_usec(pkt->ts)); pom_mutex_unlock(&tpriv->pkt_queue_lock); // Lock the processing lock pom_rwlock_rlock(&core_processing_lock); // Update the current clock if (core_clock[tpriv->thread_id] < pkt->ts) // Make sure we keep it monotonous core_clock[tpriv->thread_id] = pkt->ts; //pomlog(POMLOG_DEBUG "Thread %u processing ...", pthread_self()); if (core_process_packet(pkt) == POM_ERR) { core_run = 0; pom_rwlock_unlock(&core_processing_lock); break; } // Process timers if (timers_process() != POM_OK) { pom_rwlock_unlock(&core_processing_lock); break; } pom_rwlock_unlock(&core_processing_lock); if (packet_release(pkt) != POM_OK) { pomlog(POMLOG_ERR "Error while releasing the packet"); break; } debug_core("thread %u : Processed packet %p (%u.%06u)", tpriv->thread_id, pkt, pom_ptime_sec(pkt->ts), pom_ptime_usec(pkt->ts)); // Re-lock our queue for the next run pom_mutex_lock(&tpriv->pkt_queue_lock); } halt("Processing thread encountered an error", 1); end: packet_info_pool_cleanup(); return NULL; }
void *core_processing_thread_func(void *priv) { struct core_processing_thread *tpriv = priv; pom_mutex_lock(&core_pkt_queue_mutex); while (core_run) { while (!core_pkt_queue_head && !tpriv->pkt_queue_head) { if (core_thread_active == 0) { if (core_get_state() == core_state_finishing) core_set_state(core_state_idle); } if (!core_run) { pom_mutex_unlock(&core_pkt_queue_mutex); return NULL; } if (pthread_cond_wait(&core_pkt_queue_restart_cond, &core_pkt_queue_mutex)) { pomlog(POMLOG_ERR "Error while waiting for restart condition : %s", pom_strerror(errno)); // Should probably abort here return NULL; } } core_thread_active++; struct core_packet_queue *tmp = NULL; // Dequeue packets from our own queue first struct packet *pkt = NULL; if (tpriv->pkt_queue_head) { tmp = tpriv->pkt_queue_head; pkt = tmp->pkt; tpriv->pkt_queue_head = tmp->next; if (tpriv->pkt_queue_head) tpriv->pkt_queue_head->prev = NULL; else tpriv->pkt_queue_tail = NULL; } else { tmp = core_pkt_queue_head; pkt = tmp->pkt; // Remove the packet from the main queue core_pkt_queue_head = tmp->next; if (core_pkt_queue_head) core_pkt_queue_head->prev = NULL; else core_pkt_queue_tail = NULL; } // Add it to the unused list memset(tmp, 0, sizeof(struct core_packet_queue)); tmp->next = core_pkt_queue_unused; if (tmp->next) tmp->next->prev = tmp; core_pkt_queue_unused = tmp; core_pkt_queue_usage--; pom_mutex_unlock(&core_pkt_queue_mutex); // Lock the processing thread if (pthread_rwlock_rdlock(&core_processing_lock)) { pomlog(POMLOG_ERR "Error while locking the processing lock : %s", pom_strerror(errno)); abort(); return NULL; } // Update the current clock pom_mutex_lock(&core_clock_lock); memcpy(&core_clock, &pkt->ts, sizeof(struct timeval)); pom_mutex_unlock(&core_clock_lock); //pomlog(POMLOG_DEBUG "Thread %u processing ...", pthread_self()); if (core_process_packet(pkt) == POM_ERR) { core_run = 0; halt("Packet processing encountered an error", 1); pthread_cond_broadcast(&core_pkt_queue_restart_cond); pthread_rwlock_unlock(&core_processing_lock); return NULL; } // Process timers if (timers_process() != POM_OK) { pthread_rwlock_unlock(&core_processing_lock); return NULL; } if (pthread_rwlock_unlock(&core_processing_lock)) { pomlog(POMLOG_ERR "Error while releasing the processing lock : %s", pom_strerror(errno)); break; } if (packet_pool_release(pkt) != POM_OK) { pomlog(POMLOG_ERR "Error while releasing the packet to the pool"); break; } pom_mutex_lock(&core_pkt_queue_mutex); if (pthread_cond_broadcast(&core_pkt_queue_restart_cond)) { pomlog(POMLOG_ERR "Error while signaling the done condition : %s", pom_strerror(errno)); pom_mutex_unlock(&core_pkt_queue_mutex); break; } core_thread_active--; } pom_mutex_unlock(&core_pkt_queue_mutex); halt("Processing thread encountered an error", 1); return NULL; }