Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "priothreads.h"
- #include <pthread.h>
- #define MAX_SIZE 8
- /* inclua aqui as bibliotecas que precisar */
- #include <stdlib.h>
- #include <stdio.h>
- /* adicione o que for preciso para uma thread ter prioridade e ficar bloqueada esperando sua vez de executar */
- typedef struct{
- pthread_t thread_id;
- unsigned int prioridade;
- void *(*funcao) (void *);
- void *parametros;
- } pt_thread_ctx;
- /* Recomendo declarar tipos e estruturas internas aqui. */
- pthread_mutex_t barrier_called_mutex;
- int barrier_called;
- pthread_mutex_t on_processor_mutex;
- pt_thread_ctx **on_processor;
- pthread_cond_t queue_cond[MAX_SIZE];
- pthread_mutex_t threads_per_queue_mutex[MAX_SIZE];
- int threads_per_queue[MAX_SIZE];
- unsigned int total_processors;
- pthread_mutex_t finished_threads_mutex;
- unsigned int finished_threads;
- pthread_mutex_t waiting_call_lock;
- pthread_cond_t all_processors_inuse;
- pthread_mutex_t inuse_processors_mutex;
- unsigned int inuse_processors_count;
- pthread_mutex_t total_threads_count_mutex;
- unsigned int total_threads_count;
- pthread_t scheduler_thread;
- /* Reinicializa o escalonador. Descarta todo o estado interno atual (limpa filas) e
- define o número de processadores virtuais entre 1 e 8. Default é 1 processador.
- Caso o usuário defina um número inválido de processadores, use o default.
- */
- void pt_init(unsigned int processadores){
- if(processadores > 1 && processadores <= 8) {
- total_processors = processadores;
- }
- else {
- total_processors = 1;
- }
- on_processor = (pt_thread_ctx**) malloc(total_processors * sizeof(pt_thread_ctx*));
- for(int i=0; i<(int)total_processors; i++) {
- on_processor[i] = NULL;
- }
- pthread_mutex_init(&on_processor_mutex, NULL);
- inuse_processors_count = 0;
- pthread_mutex_init(&inuse_processors_mutex, NULL);
- pthread_cond_init(&all_processors_inuse, NULL);
- finished_threads = 0;
- pthread_mutex_init(&finished_threads_mutex, NULL);
- barrier_called = 0;
- pthread_mutex_init(&barrier_called_mutex, NULL);
- total_threads_count = 0;
- pthread_mutex_init(&total_threads_count_mutex, NULL);
- pthread_mutex_init(&waiting_call_lock, NULL);
- for (int i = 0; i < MAX_SIZE; i++) {
- pthread_cond_init(&queue_cond[i], NULL);
- pthread_mutex_init(&threads_per_queue_mutex[i], NULL);
- threads_per_queue[i] = 0;
- }
- pthread_create(&scheduler_thread, NULL, scheduler, NULL);
- }
- /* Scheduler dos processadores
- é chamada na inicialização
- */
- void * scheduler() {
- while(1) {
- //wait na condição em que todos os processadores estão em uso
- pthread_mutex_lock(&inuse_processors_mutex);
- while(inuse_processors_count == total_processors) {
- pthread_cond_wait(&all_processors_inuse, &inuse_processors_mutex);
- }
- pthread_mutex_unlock(&inuse_processors_mutex);
- for (int i = 0; i < MAX_SIZE; i++) {
- pthread_mutex_lock(&threads_per_queue_mutex[i]);
- if(threads_per_queue[i] == 0) {
- pthread_mutex_unlock(&threads_per_queue_mutex[i]);
- continue;
- }
- if(is_high_priority_thread(i)) {
- threads_per_queue[i]--;
- pthread_mutex_unlock(&threads_per_queue_mutex[i]);
- pthread_mutex_lock(&inuse_processors_mutex);
- inuse_processors_count++;
- pthread_mutex_unlock(&inuse_processors_mutex);
- //Acorda a thread
- pthread_cond_signal(&queue_cond[i]);
- break;
- }
- pthread_mutex_unlock(&threads_per_queue_mutex[i]);
- }
- //Checa se vai terminar
- pthread_mutex_lock(&barrier_called_mutex);
- pthread_mutex_lock(&finished_threads_mutex);
- if(barrier_called == 1 && finished_threads == total_threads_count) {
- pthread_mutex_unlock(&barrier_called_mutex);
- pthread_mutex_unlock(&finished_threads_mutex);
- pthread_exit(NULL);
- }
- pthread_mutex_unlock(&barrier_called_mutex);
- pthread_mutex_unlock(&finished_threads_mutex);
- }
- }
- /* Checa se a thread atual é a com maior prioridade
- */
- int is_high_priority_thread(int atual) {
- for (int i = 0; i < atual; i++) {
- pthread_mutex_lock(&threads_per_queue_mutex[i]);
- if(threads_per_queue[i] > 0) {
- pthread_mutex_unlock(&threads_per_queue_mutex[i]);
- return 0;
- }
- pthread_mutex_unlock(&threads_per_queue_mutex[i]);
- }
- return 1;
- }
- /* Cria uma nova thread com a prioridade entre 1 e 8. Default é 8. Valores menores
- definem maior prioridade. Caso o usuário defina uma prioridade inválida, use o default.
- */
- void pt_spawn(unsigned int prioridade, void *(*funcao) (void *), void *parametros) {
- pt_thread_ctx *thread_ctx;
- /* crie a thread e coloque ela na fila correta */
- thread_ctx = (pt_thread_ctx*) malloc(sizeof(pt_thread_ctx));
- thread_ctx->funcao = funcao;
- thread_ctx->parametros = parametros;
- if(prioridade >= 1 && prioridade <= 8) {
- thread_ctx->prioridade = prioridade;
- }
- else thread_ctx->prioridade = 8;
- pthread_mutex_lock(&total_threads_count_mutex);
- total_threads_count++;
- pthread_mutex_unlock(&total_threads_count_mutex);
- pthread_mutex_lock(&threads_per_queue_mutex[(int) thread_ctx->prioridade - 1]);
- threads_per_queue[(int) thread_ctx->prioridade - 1]++;
- pthread_mutex_unlock(&threads_per_queue_mutex[(int) thread_ctx->prioridade - 1]);
- pthread_create(&thread_ctx->thread_id, NULL, worker_thread, (void *) thread_ctx);
- }
- /*
- Função de execução da thread
- */
- void * worker_thread(void *arg) {
- int i;
- pt_thread_ctx *thread_ctx = (pt_thread_ctx*) arg;
- //bloqueia na fila de sua prioridade
- pthread_mutex_lock(&waiting_call_lock);
- pthread_cond_wait(&queue_cond[(int)thread_ctx->prioridade - 1], &waiting_call_lock);
- pthread_mutex_unlock(&waiting_call_lock);
- //Thread foi acordada - está com o processador
- pthread_mutex_lock(&on_processor_mutex);
- for (i = 0; i < (int)total_processors; i++) {
- if (on_processor[i] == NULL) {
- on_processor[i] = thread_ctx;
- break;
- }
- }
- pthread_mutex_unlock(&on_processor_mutex);
- //Thread vai executar
- (*(thread_ctx->funcao)) (thread_ctx->parametros);
- pthread_mutex_lock(&on_processor_mutex);
- on_processor[i] = NULL;
- pthread_mutex_unlock(&on_processor_mutex);
- //Thread terminou execução, vai liberar o processador
- pthread_mutex_lock(&inuse_processors_mutex);
- if(inuse_processors_count == total_processors) {
- pthread_cond_signal(&all_processors_inuse);
- }
- inuse_processors_count--;
- pthread_mutex_unlock(&inuse_processors_mutex);
- //Contabiliza que terminou
- pthread_mutex_lock(&finished_threads_mutex);
- finished_threads++;
- pthread_mutex_unlock(&finished_threads_mutex);
- free(thread_ctx);
- pthread_exit(NULL);
- }
- /* Faz a thread atual liberar o processador, voltar ao fim da fila de sua prioridade e
- esperar o próximo escalonamento
- */
- void pt_yield() {
- pthread_t self_id = pthread_self();
- pt_thread_ctx *thread;
- //Thread se remove do processador
- pthread_mutex_lock(&on_processor_mutex);
- for(int i=0; i < (int) total_processors; i++) {
- if(on_processor[i] != NULL && pthread_equal(self_id, on_processor[i]->thread_id) != 0) {
- thread = on_processor[i];
- on_processor[i] = NULL;
- break;
- }
- }
- pthread_mutex_unlock(&on_processor_mutex);
- //Incrementa a quantidade de Threads na fila de sua prioridade
- pthread_mutex_lock(&threads_per_queue_mutex[(int)thread->prioridade - 1]);
- threads_per_queue[(int)thread->prioridade - 1]++;
- pthread_mutex_unlock(&threads_per_queue_mutex[(int)thread->prioridade - 1]);
- pthread_mutex_lock(&inuse_processors_mutex);
- if(inuse_processors_count == total_processors) {
- pthread_cond_signal(&all_processors_inuse);
- }
- inuse_processors_count--;
- pthread_mutex_unlock(&inuse_processors_mutex);
- //Thread se bloqueia em sua file de prioridade
- pthread_mutex_lock(&waiting_call_lock);
- pthread_cond_wait(&queue_cond[(int)thread->prioridade - 1], &waiting_call_lock);
- pthread_mutex_unlock(&waiting_call_lock);
- //Thread acordada
- //Thread se coloca no vetor de processador
- pthread_mutex_lock(&on_processor_mutex);
- for(int i=0; i < (int) total_processors; i++) {
- if(on_processor[i] == NULL ) {
- on_processor[i] = thread;
- break;
- }
- }
- pthread_mutex_unlock(&on_processor_mutex);
- }
- /* Espera todas as threads terminarem */
- void pt_barrier() {
- pthread_mutex_lock(&barrier_called_mutex);
- barrier_called = 1;
- pthread_mutex_unlock(&barrier_called_mutex);
- pthread_join(scheduler_thread, NULL);
- }
- /* Libera todas as estruturas de dados do escalonador */
- void pt_destroy(){
- /* destrua as threads que estão esperando nas filas... */
- pthread_mutex_destroy(&total_threads_count_mutex);
- pthread_mutex_destroy(&inuse_processors_mutex);
- pthread_mutex_destroy(&waiting_call_lock);
- pthread_mutex_destroy(&finished_threads_mutex);
- pthread_mutex_destroy(&barrier_called_mutex);
- pthread_mutex_destroy(&on_processor_mutex);
- pthread_cond_destroy(&all_processors_inuse);
- for (int i = 0; i < MAX_SIZE; i++) {
- pthread_mutex_destroy(&threads_per_queue_mutex[i]);
- pthread_cond_destroy(&queue_cond[i]);
- }
- /* libere memória da heap */
- free(on_processor);
- }
- #include "simplegrade.h"
- #include "priothreads.h"
- #include <pthread.h>
- /** DRAFT **/
- struct contador{
- pthread_mutex_t * mutex;
- int contador;
- };
- void * incrementa(void *arg){
- struct contador *cp = (struct contador *)arg;
- printf("incrementa inicioun");
- pthread_mutex_lock(cp->mutex);
- cp->contador++;
- pthread_mutex_unlock(cp->mutex);
- printf("incrementa terminoun");
- return NULL;
- }
- void teste_foo_bar(){
- DESCRIBE("Exemplo simples de teste");
- struct contador c;
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- c.mutex = &mutex;
- c.contador = 0;
- WHEN("Duas threads incrementam um contador");
- IF("Contador iniciou com zero");
- THEN("Contador deve ter o valor dois");
- pt_init(1);
- pt_spawn(1, incrementa, (void *)&c);
- pt_spawn(2, incrementa, (void *)&c);
- pt_barrier();
- pt_destroy();
- pthread_mutex_destroy(&mutex);
- isEqual(c.contador,2,1);
- }
- #ifndef _SIMPLEGRADE_H_
- #define _SIMPLEGRADE_H_
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #define KNRM "x1B[0m"
- #define KRED "x1B[31m"
- #define KGRN "x1B[32m"
- #define KYEL "x1B[33m"
- #define KBLU "x1B[34m"
- #define KMAG "x1B[35m"
- #define KCYN "x1B[36m"
- #define KWHT "x1B[37m"
- int maxgrade=0;
- int currmaxgrade=0;
- int grade=0;
- /* or else we will calculate it by the running tests */
- /* joke is on you if you use negative grades... */
- #define MAXGRADE(max) maxgrade=max
- int GETGRADE(){
- return grade;
- }
- int GETMAXGRADE(){
- if (maxgrade)
- return maxgrade;
- else return currmaxgrade;
- }
- void GRADEME(){
- if (!maxgrade)
- maxgrade = currmaxgrade;
- int tmp = (int) ((grade / (float) maxgrade)*100);
- if (grade < maxgrade*.7){
- printf("You did %s %d %s out of %d -- grade %d/100n", KRED, grade, KNRM, maxgrade, tmp);
- }
- else{
- printf("You did %s %d %s out of %d -- grade %d/100n", KGRN, grade, KNRM, maxgrade, tmp);
- }
- }
- void DESCRIBE(char* text);
- void WHEN(char* text);
- void IF(char* text);
- void THEN(char* text);
- void DESCRIBE(char* text) {
- printf("%s-- %s --%sn",KCYN, text, KNRM);
- }
- void WHEN(char* text) {
- printf("%s when:%s %sn",KYEL, KNRM, text);
- }
- void IF(char* text) {
- printf("%s if:%s %sn",KYEL, KNRM, text);
- }
- void THEN(char* text) {
- printf("%s then:%s %sn",KYEL, KNRM, text);
- }
- void isNull(void* ptr, int points) {
- currmaxgrade+=points;
- if (ptr == NULL) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n pointer is not null%sn", KRED, KNRM);
- }
- }
- void isNotNull(void * ptr, int points) {
- currmaxgrade+=points;
- if (ptr != NULL) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n pointer is not null%sn", KRED, KNRM);
- }
- }
- void isGreaterThan(int num, int value, int points) {
- currmaxgrade+=points;
- if (num > value) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n got: %d > %d %sn", KRED, num, value, KNRM);
- }
- }
- void isEqual(int num, int value, int points) {
- currmaxgrade+=points;
- if (num == value) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n got: %d == %d %sn", KRED, num, value, KNRM);
- }
- }
- void isEqual_long(unsigned long long num, unsigned long long value, int points) {
- currmaxgrade+=points;
- if (num == value) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n got: %llu == %llu %sn", KRED, num, value, KNRM);
- }
- }
- void isNotEqual(int num, int value, int points) {
- currmaxgrade+=points;
- if (num != value) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n got: %d != %d %sn",KRED, num, value, KNRM);
- }
- }
- void isLesserThan(int num, int value, int points) {
- currmaxgrade+=points;
- if (num < value) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- } else {
- printf("%s NOT PASSED!n got: %d < %d %sn",KRED, num, value, KNRM);
- }
- }
- /* because floating points ops are not commutative nor associative */
- void isNear(float num, float value, int decimals, int points){
- currmaxgrade+=points;
- float diff = fabs(num - value);
- /* check for nearest integers */
- if (diff <= pow(10,(-decimals))) {
- printf("%s PASSED!n%s", KGRN, KNRM);
- grade+=points;
- }else {
- printf("%s NOT PASSED!n got: %f , expecting %f %sn",KRED, num, value, KNRM);
- }
- }
- #endif //_SIMPLETEST_H
- CC=gcc
- CFLAGS=-Wall -Wextra -O0 -g -std=c11 -pthread #-Werror para versao final
- LDFLAGS=-lm
- .PHONY: all
- all: grade
- priothreads.o: priothreads.h priothreads.c
- $(CC) $(CFLAGS) -c priothreads.c
- test: priothreads.o test.c
- $(CC) $(CFLAGS) -o test priothreads.o test.c $(LDFLAGS)
- grade: test
- ./test
- clean:
- rm -rf *.o test
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement