/*********************************************************************************** * * Este programa não faz parte do curso sobre tempo real do Laboratorio Embry-Riddle * embora tenha sido inspirado pelos demais experimentos que fazem parte. * * Experimento # 5 na disciplina de Sistemas Operacionais da PUC-Campinas * Originalmente programado por Florian Weizenegger * Data: 25/08/2003 * * Proposito: O proposito deste programa e o de permitir ao aluno perceber * o que vem a ser um thread, de maneira tal que consiga distingui-lo de * um processo. Além disso, são usados os principais comandos para criação * e manipulação de threads. * O problema dos produtores e consumidores sobre um buffer circular é * usado como assunto, permitindo que o aluno experimente duas implementações * diferentes para sua solução. Desta maneira, além dos threads propriamente * ditos, tambem locks e semaforos sao usados para garantir sincronizacao * de threads. * *************************************************************************************/ /* * Includes Necessarios */ #include /* para poder manipular threads */ #include /* para printf() */ /* * Constantes Necessarias */ #define NUM_THREADS 1 #define SIZEOFBUFFER 50000 #define NO_OF_ITERATIONS 100000 /* * O tipo pthread_t permite a declaração de uma variável que recebe * um id quando o thread é criado. Posteriormente, esse id pode ser * usado em comandos de controle para threads. * Seguem dois vetores para ids, para um numero de threads igual a * constante NUM_THREADS */ pthread_t consumers[NUM_THREADS]; pthread_t producers[NUM_THREADS]; /* * Variaveis Necessarias */ int buffer[SIZEOFBUFFER]; /* Este e o buffer circular */ int *start; /* apontara para a primeira posicao do buffer */ int *rp; /* e o apontador para consumir o proximo item do buffer */ int *wp; /* e o apontador para produzir o proximo item do buffer */ /* * Rotina para produzir um item toAdd no buffer */ int myadd(int toAdd) { //verificacao se o buffer nao esta cheio if ((rp != (wp+1)) && (wp != rp + SIZEOFBUFFER - 1)) { *wp = toAdd; wp++; //verificacao se wp chegou a ultima posicao do buffer if (wp == (start + SIZEOFBUFFER)) { wp = start; /* realiza a circularidade no buffer */ } return 1; } else return 0; } /* * Rotina para consumir um item do buffer e coloca-lo em retValue */ int myremove() { //verificacao se o buffer nao esta vazio if (wp != rp) { int retValue = *rp; rp++; //verificacao se rp chegou a ultima posicao do buffer if (rp == (start + SIZEOFBUFFER)) { rp = start; /* realiza a circularidade no buffer */ } return retValue; } else return 0; } /* * A rotina produce e responsavel por chamar myadd para que seja * colocado o valor 10 em uma posicao do buffer NO_OF_ITERATIONS vezes */ void *produce(void *threadid) { int i = 0; int sum = 0; int ret = 0; printf("Produtor #%d iniciou...\n", threadid); while (i < NO_OF_ITERATIONS) { ret = myadd(10); if (ret) { i++; sum += 10; } } printf("Soma produzida pelo Produtor #%d : %d\n", threadid, sum); pthread_exit(NULL); } /* * A rotina consume e responsavel por chamar myremove para que seja * retorando um dos valores existentes no buffer NO_OF_ITERATIONS vezes */ void *consume(void *threadid) { int i = 0; int sum = 0; int ret = 0; printf("Consumidor #%d iniciou...\n", threadid); while (i < NO_OF_ITERATIONS) { ret = myremove(); if (ret != 0) { i++; sum += ret; } } printf("Total consumido pelo Consumidor #%d : %d\n", threadid, sum); pthread_exit(NULL); } /* * Rotina Principal (que tambem e o thread principal, quando executada) */ int main(int argc, char *argv[]) { int tp, tc; int i; start = &buffer[0]; wp = start; rp = start; for (i=0;i