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; }