/* ---------------------------------------------------------- * Monitor Thread * * Monitor thread waits for child processes to end and * saves their status and end time. * If there are no children, monitor thread is suspended waiting for any new * child process. * ---------------------------------------------------------- */ void *monitor(void) { int child_pid; int child_status; time_t endtime; while (1) { pthread_mutex_lock_(&mutex); while (child_count <= 0)pthread_cond_wait_(&new_child, &mutex); pthread_mutex_unlock_(&mutex); child_pid = wait(&child_status); time(&endtime); pthread_mutex_lock_(&mutex); update_terminated_process(lst, child_pid, endtime, child_status); enqueue(writing_queue, child_pid); /* put process on hold to be written */ --child_count; pthread_cond_signal_(&write_cond); pthread_cond_signal_(&max_par); pthread_mutex_unlock_(&mutex); pthread_mutex_lock_(&mutex); if (exit_command != 0 && child_count <= 0) { pthread_mutex_unlock_(&mutex); pthread_exit(NULL); } pthread_mutex_unlock_(&mutex); } }
/*/////////////////////////////////////// ///////////// THREAD FUNCTION /////////// ///////////////////////////////////////*/ void *waitThread() { int childID, status, iteration = 0; char linha[256]; FILE *f; f = fopen("log.txt", "a+"); if (f == NULL) { perror(error_fopen); } while (fgets(linha, 256, f) != NULL) { iteration++; } if (pthread_mutex_lock(&mutex) != 0) { perror(error_mutex_lock); } sscanf(linha, "total execution time: %d", &timeTotal); if (pthread_mutex_unlock(&mutex) != 0) { perror(error_mutex_unlock); } if (iteration > 0) { iteration = iteration / 3; } while (1){ if (pthread_mutex_lock(&mutex) != 0) { perror(error_mutex_lock); } while((numChildren == 0) && (isExit == false)) { pthread_cond_wait(&can_wait, &mutex); } if (pthread_mutex_unlock(&mutex) != 0) { perror(error_mutex_unlock); } if (numChildren > 0) { childID = wait(&status); if (pthread_mutex_lock(&mutex) != 0) { perror(error_mutex_lock); } timeTotal += update_terminated_process(l, childID, status, time(NULL)); file_print(f, l, iteration, childID, timeTotal); iteration++; numChildren--; if (pthread_cond_signal(&can_execute) != 0) { perror(error_cond_execute); } if (pthread_mutex_unlock(&mutex) != 0) { perror(error_mutex_unlock); } } else if (isExit == true) { if (fclose(f) != 0) { perror(error_fclose_log); } pthread_exit(NULL); } } }
/* Child process monitoring function */ void *process_monitor() { pid_t child_pid; /* pid of zombie child */ int status, time_interval; /* child exit status; interval between time_t's */ while(true) { mutex_lock(&g_mutex); if(g_num_children > 0) { mutex_unlock(&g_mutex); child_pid = wait(&status); if(child_pid < 0) { if(errno == EINTR) /* Waiting interrupted */ continue; else handle_error("wait"); } mutex_lock(&g_mutex); time_interval = update_terminated_process(g_lst_children, child_pid, status, time(NULL)); if(time_interval < 0) { fprintf(stderr, "update_terminated_process: interval is negative\n"); fprintf(stderr, "Not logging process %d..\n", child_pid); } else { g_total_time += time_interval; fprintf(g_log_file, "iteracao %d\n" \ "PID: %d execution time: %02d s\n" \ "total execution time: %02d s\n", g_iterations++, child_pid, time_interval, g_total_time); f_flush(g_log_file); } --g_num_children; cond_signal(&g_child_cv); mutex_unlock(&g_mutex); } else if(g_monitoring) { while(g_num_children == 0 && g_monitoring) cond_wait(&g_monitoring_cv, &g_mutex); mutex_unlock(&g_mutex); } else break; } mutex_unlock(&g_mutex); return NULL; }
void *tarefa_monitora(){ if(__DEBUG__){ printf("\e[36m[ DEBUG ]\e[0m Estamos na tarefa_monitora %d\n", (int) pthread_self() ); } int status; while(1){ /* Esperar que existam filhos em execucao */ sem_wait(&filhos_em_execucao); pthread_mutex_lock(&children_mutex); if(numChildren > 0) { pthread_mutex_unlock(&children_mutex); // aguarda pela terminacao dos processos filhos pid_t ret = wait(&status); /*Assinalar que existe menos um filho em execucao*/ sem_post(&lim_processos); if(__DEBUG__) printf("\e[36m[ DEBUG ]\e[0m Process %d finished\n", (int) ret ); // regista o pid do processo acabado de terminar e o respectivo return status na lista if(WIFEXITED(status)){ //atulizacao do tempo de fim do processo pthread_mutex_lock(&lista_mutex); update_terminated_process(lista_processos, ret, time(NULL), WEXITSTATUS(status)); pthread_mutex_unlock(&lista_mutex); }else{ //Eliminacao da lista de um processo no qual ocorreu um erro (ex. seg fault) pthread_mutex_lock(&lista_mutex); delete_process(lista_processos, ret); pthread_mutex_unlock(&lista_mutex); printf("\e[31m[ ERROR ]\e[0m Process %d terminated Abruptly\n", ret ); } pthread_mutex_lock(&children_mutex); numChildren--; pthread_mutex_unlock(&children_mutex); }else{ if(_exit_ctrl){
void *tarefa_monitor(){ int pid, estado; while(1){ pthread_mutex_lock(&mutex); if(nfilhos < 1) { if(exit_ative){ pthread_mutex_unlock(&mutex); break; } pthread_mutex_unlock(&mutex); sleep(1); continue; } else { pthread_mutex_unlock(&mutex); pid = wait(&estado); if (pid < 0) { if (errno == EINTR) { /* Este codigo de erro significa que chegou signal que interrompeu a espera pela terminacao de filho; logo voltamos a esperar */ continue; } else { perror("Error waiting for child."); exit (EXIT_FAILURE); } } // Atualizar a lista com as informacoes do filho esperado no wait pthread_mutex_lock(&mutex); update_terminated_process(list, pid, estado, WIFEXITED(estado),time(NULL)); nfilhos--; pthread_mutex_unlock(&mutex); continue; } } pthread_exit(NULL); }
/*=================================================== = Tarefa monitora = ===================================================*/ void *tarefa_monitora(){ int pid; // Pid do processo filho int estado; // Valor do estado devolvido pelo wait do processo filho time_t starttime; // Tempo inicial do processo filho time_t endtime; // Tempo final do processo filho while(1){ mutex_lock(); /** * Verificar se existem processos filhos para monitorizar * ou se a par-shell pretende fazer exit */ while(!exit_ative && nfilhos == 0){ // exit_ative == false && nfilhos == 0 if(pthread_cond_wait(&podeMonitorizar,&mutex) != 0){ perror("Erro no pthread_cond_wait na tarefa_monitora: "); } } /** * Verificar se a par-shell pretende fazer exit quando não tem processos filho */ if(nfilhos == 0){ if(exit_ative){ mutex_unlock(); pthread_exit(NULL); } mutex_unlock(); } /** * A par-shell tem processos filho para monitorizar */ else{ mutex_unlock(); /** * Realizar wait por um processo filho */ pid = wait(&estado); if (pid < 0) { if (errno == EINTR) { /** * Este codigo de erro significa que chegou signal que interrompeu * a espera pela terminação de filho; logo voltamos a esperar */ continue; } else { perror("Error waiting for child\n"); exit(EXIT_FAILURE); } } // Obter tempo final de execução do processo filho endtime = time(NULL); mutex_lock(); /** * Atualizar a lista de processos filhos com as informações necessárias */ if ((starttime = update_terminated_process(list, pid, estado,WIFEXITED(estado),endtime)) < 0){ // Verificar se houve erro na atualizacao da lista de processos filhos -> nao existe o pid na lista perror("Erro na atualizacao da lista de processos filhos: "); } /** * Atualizar os valores de iteracao e tempo_total_execucao */ iteracao += 1; tempo_total_execucao += difftime(endtime,starttime); // Escrever no ficheiro de texto fprintf(ficheiro_log, "iteracao %d\n",iteracao); // iteracao fprintf(ficheiro_log, "pid: %d execution time: %g s\n",pid,difftime(endtime,starttime)); // informações do filho fprintf(ficheiro_log, "total execution time: %g s\n",tempo_total_execucao); // tempo total de execução if(fflush(ficheiro_log) < 0) perror("Erro no fflush de escrita no log.txt: "); // Diminuir o contador do número de filhos em execução nfilhos--; // Sinalizar a variavel de condição relacionada com a criação de novos processos filho if(pthread_cond_signal(&podeCriarFilhos) != 0){ perror("Erro no pthread_cond_signal na tarefa_monitora: "); } mutex_unlock(); } } }