void keyboard_get(int size, int *buffer) { if(size > currentBufPos) { size = currentBufPos; } memcpy(buffer, keyboardBuffer, size); removeFromBuffer(size); }
void * leitor(void * arg) { int fileid; long int value; char file[LENGTH+1], fileBuffer[13]; char compstr[LENGTH+1]; while(exitFlag != 0){ removeFromBuffer(fileBuffer); if (exitFlag == 0) break; fileid = open(fileBuffer, O_RDONLY); if (fileid == -1){ printf("File %s does not exist or failed to open\n", fileBuffer); continue; } if(flock(fileid, LOCK_SH || LOCK_NB) == -1){ printf("Read lock did not succeed\n"); continue; } if(read(fileid, file, sizeof(char)*LENGTH)==-1){ printf("Could not read file %s\n", fileBuffer); continue; } file[LENGTH] = '\0'; /* Transforms the characters read to the buffer on the read() function into a String with a '\0' */ if (checkStr(file) == 0) { strcpy(compstr, file); if(checkAllStr(fileid, compstr)==0) { printf("File %s is according to format\n", fileBuffer); } else { printf("File %s not according to format\n", fileBuffer); } } else { printf("File %s has invalid first string\n", fileBuffer); } if(flock(fileid, LOCK_UN)==-1){ printf("Could not unlock the read access to the file %s\n", fileBuffer); } if(close(fileid)==-1){ printf("Could not close the file %s\n", fileBuffer); } } pthread_exit(NULL); }
char keyboard_getchar() { // debugMSG("Getting char from keyboard buffer...\n", KEYBOARD_DB_LEVEL); char result; if(!currentBufPos == 0) { result = keyboardBuffer[currentBufPos - 1]; removeFromBuffer(1); } else{ result = 0; } return result; }
double adaptativeQuadrature(int id, double (*func)(double), double a, double b, double err, int preparingBuffer) { double m, funcB, funcSleft, funcSright, areaS1, areaS2, areaB; params *input; int preservePos; /* funcB, funcSleft, funcSright: alturas dos retangulos, calculado a partir do ponto médio entre cada um dos retangulos. areaB: area do retangulo maior (b - a) * funcB areaS1, areaS2: area dos retangulos menores (m - a) * funcSleft e (b - m) * funcSright (left e right indicam apenas se está a esquerda ou direita do ponto médio) */ m = getMiddle(a, b); funcB = func(m); funcSleft = func(getMiddle(a, m)); funcSright = func(getMiddle(m, b)); areaB = (b - a) * funcB; areaS1 = (m - a) * funcSleft; areaS2 = (b - m) * funcSright; // agora, se o módulo da diferença entre a area do retangulo maior e da soma dos retangulos menores for maior que o erro máximo, calcula a área dos dois intervalos [a,m], [b,m] // porém, agora na versão concorrente, checamos se existe a possibilidade de delegar essa tarefa a uma nova threads // assim, se nem todas as threads foram iniciadas, então iremos iniciar uma nova thread que ficará responsável por um dos retangulos e a thread atual fica responsável apenas pelo outro retangulo. // senão, apenas retorna o valor da area do retangulo maior if (fabs(areaB - (areaS1 + areaS2)) > err) { if (!allinstantiated) { //mesmo estando fora de um mutex, não há problema por ter uma confirmação dentro. pthread_mutex_lock(&theMutex); if (instantiated < nThreads) { // checa se é possível instanciar. input = (params *) malloc(sizeof(params)); input->id = instantiated; input->err = err; input->a = m; input->b = b; input->func = func; pthread_create(&threads[instantiated], NULL, calcIntegral, (void *) input); instantiated++; pthread_mutex_unlock(&theMutex); areaB = adaptativeQuadrature(id, func, a, m, err, preparingBuffer); } else { //se não for, apenas avisa que não é mais possível instanciar e continua a trabalhar normalmente allinstantiated = 1; pthread_mutex_unlock(&theMutex); areaB = adaptativeQuadrature(id, func, a, m, err, preparingBuffer) + adaptativeQuadrature(id, func, m, b, err, preparingBuffer); } } else { // Preparing buffer é para que não ocorra que threads que antes estavam ociosas busquem por threads atualmente ociosas para calcular um retangulo // é necessário para que o processamento continue, e não é problema pois a ociosidade da outra thread acabará rapido, basta uma thread ainda no cálculo inicial a chame if (!anythingSent && anyoneFree && !preparingBuffer) { // checa se tem alguém ocioso e se ninguém enviou dado ainda pthread_mutex_lock(&theMutex); if (!anythingSent) { // recheca a condição, agora numa seção crítica (entre locks) globala = m; globalb = b; anythingSent = id + 1; freePos = pos[id]; pos[id] = (pos[id] + 1 < TAM) ? pos[id] + 1 : 0; anyoneFree = 0; preservePos = freePos; // avisa as threads que estão esperando que já enviou dados pthread_cond_broadcast(&theCond); pthread_mutex_unlock(&theMutex); areaB = removeFromBuffer(id, preservePos) + adaptativeQuadrature(id, func, a, m, err, preparingBuffer); } else { // senão, simplesmente avisa que saiu do loop e continua execução pthread_cond_broadcast(&theCond); pthread_mutex_unlock(&theMutex); areaB = adaptativeQuadrature(id, func, a, m, err, preparingBuffer) + adaptativeQuadrature(id, func, m, b, err, preparingBuffer); } } else { // senão, simplesmente calcula mais retangulos areaB = adaptativeQuadrature(id, func, a, m, err, preparingBuffer) + adaptativeQuadrature(id, func, m, b, err, preparingBuffer); } } } return areaB; }