//----------------------------------------------------------------------------------------------------- //Function called by worker thread. Processes items in IN_QUEUE by retrieving them, executing them, // then adding them to OUT_QUEUE. //----------------------------------------------------------------------------------------------------- void* process_rules(void* arg) { rule_t* cur_rule; while(1) { //If something gets stuck in dep_q this could be a problem, but helper thread should // exit if something is stuck //Only allow as many threads into in_q as items in the in_q sem_wait(&jobs_sem); //Check exit condition if(adding_Rules == 0 && in_q->index == 0 && dep_q->index == 0) break; //Get rule, execute, and put in out_q if((cur_rule = get_rule(IN_QUEUE, NULL)) == NULL) { fprintf(stderr, "Error, tried to access NULL queue\n"); continue; } //printf("EXECUTE(%u): %s\n", (unsigned int)pthread_self(), cur_rule->target); pthread_mutex_lock(&exec_mutex); fake_exec(cur_rule); pthread_mutex_unlock(&exec_mutex); add_rule(OUT_QUEUE, cur_rule); } //printf("Worker(%u) exiting\n", (unsigned int)pthread_self()); return NULL; }
void* helper_thread(void* args) { //Unpack args ARG_HOLDER* argholder = (ARG_HOLDER*)(args); rule_node_t* queue = argholder->rule_queue; int queue_size = argholder->max_queue_length; argholder->threads_not_done++; int threadno = argholder->threads_not_done; int ql = queue_length(queue) - 1; while (!argholder->finished_adding || ql > 0) { //Check queue and "execute" targets on it int full_queue = 0; while (!argholder->done && ql == 0) { //Wait for the queue length to go up cond_wait(&queue_empty, &mutex); ql = queue_length(queue) - 1; } if (ql == queue_size) { full_queue = 1; } if (ql > 0 && !argholder->done) { //Remove the first target from the queue and "execute" it sem_wait(&sem_lock); rule_node_t* first_node = queue->next; rule_node_t* qnode = first_node->next; rule_t* cur_rule = first_node->rule; queue->next = qnode; free(first_node); sem_post(&sem_lock); //If the queue was full, signal the main thread that it is not if (full_queue) { pthread_cond_broadcast(&queue_full); } fake_exec(cur_rule); //Put rule on output queue rule_node_t* out_first = argholder->output_queue; rule_node_t* output = (rule_node_t*)malloc(sizeof(rule_node_t)); output->rule = cur_rule; output->next = out_first; argholder->output_queue = output; } ql = queue_length(queue) - 1; } argholder->done = 1; argholder->threads_not_done--; pthread_cond_broadcast(&queue_empty); pthread_cond_signal(&finished_execution); //printf("Thread %d exiting.\n", threadno); return NULL; }