Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.53 KB | None | 0 0
  1. #include "priothreads.h"
  2. #include <pthread.h>
  3.  
  4. #define MAX_SIZE 8
  5.  
  6. /* inclua aqui as bibliotecas que precisar */
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9.  
  10. /* adicione o que for preciso para uma thread ter prioridade e ficar bloqueada esperando sua vez de executar */
  11. typedef struct{
  12. pthread_t thread_id;
  13. unsigned int prioridade;
  14. void *(*funcao) (void *);
  15. void *parametros;
  16. } pt_thread_ctx;
  17.  
  18. /* Recomendo declarar tipos e estruturas internas aqui. */
  19.  
  20. pthread_mutex_t barrier_called_mutex;
  21. int barrier_called;
  22.  
  23. pthread_mutex_t on_processor_mutex;
  24. pt_thread_ctx **on_processor;
  25.  
  26. pthread_cond_t queue_cond[MAX_SIZE];
  27. pthread_mutex_t threads_per_queue_mutex[MAX_SIZE];
  28. int threads_per_queue[MAX_SIZE];
  29.  
  30. unsigned int total_processors;
  31.  
  32. pthread_mutex_t finished_threads_mutex;
  33. unsigned int finished_threads;
  34.  
  35. pthread_mutex_t waiting_call_lock;
  36.  
  37. pthread_cond_t all_processors_inuse;
  38. pthread_mutex_t inuse_processors_mutex;
  39. unsigned int inuse_processors_count;
  40.  
  41. pthread_mutex_t total_threads_count_mutex;
  42. unsigned int total_threads_count;
  43.  
  44. pthread_t scheduler_thread;
  45.  
  46. /* Reinicializa o escalonador. Descarta todo o estado interno atual (limpa filas) e
  47. define o número de processadores virtuais entre 1 e 8. Default é 1 processador.
  48. Caso o usuário defina um número inválido de processadores, use o default.
  49. */
  50. void pt_init(unsigned int processadores){
  51.  
  52. if(processadores > 1 && processadores <= 8) {
  53. total_processors = processadores;
  54. }
  55. else {
  56. total_processors = 1;
  57. }
  58.  
  59. on_processor = (pt_thread_ctx**) malloc(total_processors * sizeof(pt_thread_ctx*));
  60.  
  61. for(int i=0; i<(int)total_processors; i++) {
  62. on_processor[i] = NULL;
  63. }
  64. pthread_mutex_init(&on_processor_mutex, NULL);
  65.  
  66. inuse_processors_count = 0;
  67. pthread_mutex_init(&inuse_processors_mutex, NULL);
  68. pthread_cond_init(&all_processors_inuse, NULL);
  69.  
  70. finished_threads = 0;
  71. pthread_mutex_init(&finished_threads_mutex, NULL);
  72.  
  73. barrier_called = 0;
  74. pthread_mutex_init(&barrier_called_mutex, NULL);
  75.  
  76. total_threads_count = 0;
  77. pthread_mutex_init(&total_threads_count_mutex, NULL);
  78.  
  79. pthread_mutex_init(&waiting_call_lock, NULL);
  80.  
  81. for (int i = 0; i < MAX_SIZE; i++) {
  82. pthread_cond_init(&queue_cond[i], NULL);
  83. pthread_mutex_init(&threads_per_queue_mutex[i], NULL);
  84. threads_per_queue[i] = 0;
  85. }
  86.  
  87. pthread_create(&scheduler_thread, NULL, scheduler, NULL);
  88. }
  89.  
  90. /* Scheduler dos processadores
  91. é chamada na inicialização
  92. */
  93. void * scheduler() {
  94.  
  95. while(1) {
  96.  
  97. //wait na condição em que todos os processadores estão em uso
  98. pthread_mutex_lock(&inuse_processors_mutex);
  99. while(inuse_processors_count == total_processors) {
  100. pthread_cond_wait(&all_processors_inuse, &inuse_processors_mutex);
  101. }
  102. pthread_mutex_unlock(&inuse_processors_mutex);
  103.  
  104. for (int i = 0; i < MAX_SIZE; i++) {
  105.  
  106. pthread_mutex_lock(&threads_per_queue_mutex[i]);
  107.  
  108. if(threads_per_queue[i] == 0) {
  109. pthread_mutex_unlock(&threads_per_queue_mutex[i]);
  110. continue;
  111. }
  112.  
  113. if(is_high_priority_thread(i)) {
  114.  
  115. threads_per_queue[i]--;
  116.  
  117. pthread_mutex_unlock(&threads_per_queue_mutex[i]);
  118.  
  119. pthread_mutex_lock(&inuse_processors_mutex);
  120. inuse_processors_count++;
  121. pthread_mutex_unlock(&inuse_processors_mutex);
  122.  
  123. //Acorda a thread
  124. pthread_cond_signal(&queue_cond[i]);
  125.  
  126. break;
  127. }
  128.  
  129. pthread_mutex_unlock(&threads_per_queue_mutex[i]);
  130. }
  131.  
  132. //Checa se vai terminar
  133. pthread_mutex_lock(&barrier_called_mutex);
  134. pthread_mutex_lock(&finished_threads_mutex);
  135.  
  136. if(barrier_called == 1 && finished_threads == total_threads_count) {
  137.  
  138. pthread_mutex_unlock(&barrier_called_mutex);
  139. pthread_mutex_unlock(&finished_threads_mutex);
  140.  
  141. pthread_exit(NULL);
  142. }
  143. pthread_mutex_unlock(&barrier_called_mutex);
  144. pthread_mutex_unlock(&finished_threads_mutex);
  145. }
  146. }
  147.  
  148. /* Checa se a thread atual é a com maior prioridade
  149. */
  150. int is_high_priority_thread(int atual) {
  151. for (int i = 0; i < atual; i++) {
  152. pthread_mutex_lock(&threads_per_queue_mutex[i]);
  153. if(threads_per_queue[i] > 0) {
  154. pthread_mutex_unlock(&threads_per_queue_mutex[i]);
  155. return 0;
  156. }
  157. pthread_mutex_unlock(&threads_per_queue_mutex[i]);
  158. }
  159.  
  160. return 1;
  161. }
  162.  
  163. /* Cria uma nova thread com a prioridade entre 1 e 8. Default é 8. Valores menores
  164. definem maior prioridade. Caso o usuário defina uma prioridade inválida, use o default.
  165. */
  166. void pt_spawn(unsigned int prioridade, void *(*funcao) (void *), void *parametros) {
  167. pt_thread_ctx *thread_ctx;
  168.  
  169. /* crie a thread e coloque ela na fila correta */
  170. thread_ctx = (pt_thread_ctx*) malloc(sizeof(pt_thread_ctx));
  171. thread_ctx->funcao = funcao;
  172. thread_ctx->parametros = parametros;
  173.  
  174. if(prioridade >= 1 && prioridade <= 8) {
  175. thread_ctx->prioridade = prioridade;
  176. }
  177. else thread_ctx->prioridade = 8;
  178.  
  179. pthread_mutex_lock(&total_threads_count_mutex);
  180. total_threads_count++;
  181. pthread_mutex_unlock(&total_threads_count_mutex);
  182.  
  183. pthread_mutex_lock(&threads_per_queue_mutex[(int) thread_ctx->prioridade - 1]);
  184. threads_per_queue[(int) thread_ctx->prioridade - 1]++;
  185. pthread_mutex_unlock(&threads_per_queue_mutex[(int) thread_ctx->prioridade - 1]);
  186.  
  187. pthread_create(&thread_ctx->thread_id, NULL, worker_thread, (void *) thread_ctx);
  188. }
  189.  
  190. /*
  191. Função de execução da thread
  192. */
  193. void * worker_thread(void *arg) {
  194. int i;
  195. pt_thread_ctx *thread_ctx = (pt_thread_ctx*) arg;
  196.  
  197. //bloqueia na fila de sua prioridade
  198. pthread_mutex_lock(&waiting_call_lock);
  199. pthread_cond_wait(&queue_cond[(int)thread_ctx->prioridade - 1], &waiting_call_lock);
  200. pthread_mutex_unlock(&waiting_call_lock);
  201. //Thread foi acordada - está com o processador
  202.  
  203. pthread_mutex_lock(&on_processor_mutex);
  204.  
  205. for (i = 0; i < (int)total_processors; i++) {
  206. if (on_processor[i] == NULL) {
  207. on_processor[i] = thread_ctx;
  208. break;
  209. }
  210. }
  211. pthread_mutex_unlock(&on_processor_mutex);
  212.  
  213. //Thread vai executar
  214. (*(thread_ctx->funcao)) (thread_ctx->parametros);
  215.  
  216. pthread_mutex_lock(&on_processor_mutex);
  217. on_processor[i] = NULL;
  218. pthread_mutex_unlock(&on_processor_mutex);
  219.  
  220. //Thread terminou execução, vai liberar o processador
  221. pthread_mutex_lock(&inuse_processors_mutex);
  222.  
  223. if(inuse_processors_count == total_processors) {
  224. pthread_cond_signal(&all_processors_inuse);
  225. }
  226.  
  227. inuse_processors_count--;
  228. pthread_mutex_unlock(&inuse_processors_mutex);
  229.  
  230. //Contabiliza que terminou
  231. pthread_mutex_lock(&finished_threads_mutex);
  232. finished_threads++;
  233. pthread_mutex_unlock(&finished_threads_mutex);
  234.  
  235. free(thread_ctx);
  236.  
  237. pthread_exit(NULL);
  238. }
  239.  
  240. /* Faz a thread atual liberar o processador, voltar ao fim da fila de sua prioridade e
  241. esperar o próximo escalonamento
  242. */
  243. void pt_yield() {
  244. pthread_t self_id = pthread_self();
  245. pt_thread_ctx *thread;
  246.  
  247. //Thread se remove do processador
  248. pthread_mutex_lock(&on_processor_mutex);
  249. for(int i=0; i < (int) total_processors; i++) {
  250. if(on_processor[i] != NULL && pthread_equal(self_id, on_processor[i]->thread_id) != 0) {
  251. thread = on_processor[i];
  252. on_processor[i] = NULL;
  253. break;
  254. }
  255. }
  256. pthread_mutex_unlock(&on_processor_mutex);
  257.  
  258. //Incrementa a quantidade de Threads na fila de sua prioridade
  259. pthread_mutex_lock(&threads_per_queue_mutex[(int)thread->prioridade - 1]);
  260. threads_per_queue[(int)thread->prioridade - 1]++;
  261. pthread_mutex_unlock(&threads_per_queue_mutex[(int)thread->prioridade - 1]);
  262.  
  263. pthread_mutex_lock(&inuse_processors_mutex);
  264. if(inuse_processors_count == total_processors) {
  265. pthread_cond_signal(&all_processors_inuse);
  266. }
  267. inuse_processors_count--;
  268. pthread_mutex_unlock(&inuse_processors_mutex);
  269.  
  270. //Thread se bloqueia em sua file de prioridade
  271. pthread_mutex_lock(&waiting_call_lock);
  272. pthread_cond_wait(&queue_cond[(int)thread->prioridade - 1], &waiting_call_lock);
  273. pthread_mutex_unlock(&waiting_call_lock);
  274. //Thread acordada
  275.  
  276. //Thread se coloca no vetor de processador
  277. pthread_mutex_lock(&on_processor_mutex);
  278. for(int i=0; i < (int) total_processors; i++) {
  279. if(on_processor[i] == NULL ) {
  280. on_processor[i] = thread;
  281. break;
  282. }
  283. }
  284. pthread_mutex_unlock(&on_processor_mutex);
  285. }
  286.  
  287. /* Espera todas as threads terminarem */
  288. void pt_barrier() {
  289. pthread_mutex_lock(&barrier_called_mutex);
  290. barrier_called = 1;
  291. pthread_mutex_unlock(&barrier_called_mutex);
  292.  
  293. pthread_join(scheduler_thread, NULL);
  294.  
  295. }
  296.  
  297. /* Libera todas as estruturas de dados do escalonador */
  298. void pt_destroy(){
  299. /* destrua as threads que estão esperando nas filas... */
  300. pthread_mutex_destroy(&total_threads_count_mutex);
  301. pthread_mutex_destroy(&inuse_processors_mutex);
  302. pthread_mutex_destroy(&waiting_call_lock);
  303. pthread_mutex_destroy(&finished_threads_mutex);
  304. pthread_mutex_destroy(&barrier_called_mutex);
  305. pthread_mutex_destroy(&on_processor_mutex);
  306.  
  307. pthread_cond_destroy(&all_processors_inuse);
  308.  
  309. for (int i = 0; i < MAX_SIZE; i++) {
  310. pthread_mutex_destroy(&threads_per_queue_mutex[i]);
  311. pthread_cond_destroy(&queue_cond[i]);
  312. }
  313.  
  314. /* libere memória da heap */
  315. free(on_processor);
  316. }
  317.  
  318. #include "simplegrade.h"
  319. #include "priothreads.h"
  320. #include <pthread.h>
  321.  
  322. /** DRAFT **/
  323.  
  324. struct contador{
  325. pthread_mutex_t * mutex;
  326. int contador;
  327. };
  328.  
  329.  
  330. void * incrementa(void *arg){
  331. struct contador *cp = (struct contador *)arg;
  332. printf("incrementa inicioun");
  333. pthread_mutex_lock(cp->mutex);
  334. cp->contador++;
  335. pthread_mutex_unlock(cp->mutex);
  336. printf("incrementa terminoun");
  337. return NULL;
  338. }
  339.  
  340.  
  341. void teste_foo_bar(){
  342. DESCRIBE("Exemplo simples de teste");
  343.  
  344. struct contador c;
  345. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  346. c.mutex = &mutex;
  347. c.contador = 0;
  348. WHEN("Duas threads incrementam um contador");
  349. IF("Contador iniciou com zero");
  350. THEN("Contador deve ter o valor dois");
  351. pt_init(1);
  352. pt_spawn(1, incrementa, (void *)&c);
  353. pt_spawn(2, incrementa, (void *)&c);
  354. pt_barrier();
  355. pt_destroy();
  356. pthread_mutex_destroy(&mutex);
  357. isEqual(c.contador,2,1);
  358. }
  359.  
  360. #ifndef _SIMPLEGRADE_H_
  361. #define _SIMPLEGRADE_H_
  362.  
  363. #include <stdio.h>
  364. #include <stdlib.h>
  365. #include <math.h>
  366.  
  367. #define KNRM "x1B[0m"
  368. #define KRED "x1B[31m"
  369. #define KGRN "x1B[32m"
  370. #define KYEL "x1B[33m"
  371. #define KBLU "x1B[34m"
  372. #define KMAG "x1B[35m"
  373. #define KCYN "x1B[36m"
  374. #define KWHT "x1B[37m"
  375.  
  376. int maxgrade=0;
  377. int currmaxgrade=0;
  378. int grade=0;
  379.  
  380. /* or else we will calculate it by the running tests */
  381. /* joke is on you if you use negative grades... */
  382. #define MAXGRADE(max) maxgrade=max
  383.  
  384. int GETGRADE(){
  385. return grade;
  386. }
  387.  
  388. int GETMAXGRADE(){
  389. if (maxgrade)
  390. return maxgrade;
  391. else return currmaxgrade;
  392. }
  393.  
  394. void GRADEME(){
  395. if (!maxgrade)
  396. maxgrade = currmaxgrade;
  397.  
  398. int tmp = (int) ((grade / (float) maxgrade)*100);
  399.  
  400. if (grade < maxgrade*.7){
  401. printf("You did %s %d %s out of %d -- grade %d/100n", KRED, grade, KNRM, maxgrade, tmp);
  402. }
  403. else{
  404. printf("You did %s %d %s out of %d -- grade %d/100n", KGRN, grade, KNRM, maxgrade, tmp);
  405. }
  406. }
  407.  
  408. void DESCRIBE(char* text);
  409. void WHEN(char* text);
  410. void IF(char* text);
  411. void THEN(char* text);
  412.  
  413. void DESCRIBE(char* text) {
  414. printf("%s-- %s --%sn",KCYN, text, KNRM);
  415. }
  416.  
  417. void WHEN(char* text) {
  418. printf("%s when:%s %sn",KYEL, KNRM, text);
  419. }
  420.  
  421. void IF(char* text) {
  422. printf("%s if:%s %sn",KYEL, KNRM, text);
  423. }
  424.  
  425. void THEN(char* text) {
  426. printf("%s then:%s %sn",KYEL, KNRM, text);
  427. }
  428.  
  429. void isNull(void* ptr, int points) {
  430. currmaxgrade+=points;
  431. if (ptr == NULL) {
  432. printf("%s PASSED!n%s", KGRN, KNRM);
  433. grade+=points;
  434. } else {
  435. printf("%s NOT PASSED!n pointer is not null%sn", KRED, KNRM);
  436. }
  437. }
  438.  
  439. void isNotNull(void * ptr, int points) {
  440. currmaxgrade+=points;
  441. if (ptr != NULL) {
  442. printf("%s PASSED!n%s", KGRN, KNRM);
  443. grade+=points;
  444. } else {
  445. printf("%s NOT PASSED!n pointer is not null%sn", KRED, KNRM);
  446. }
  447. }
  448.  
  449. void isGreaterThan(int num, int value, int points) {
  450. currmaxgrade+=points;
  451. if (num > value) {
  452. printf("%s PASSED!n%s", KGRN, KNRM);
  453. grade+=points;
  454. } else {
  455. printf("%s NOT PASSED!n got: %d > %d %sn", KRED, num, value, KNRM);
  456. }
  457. }
  458.  
  459. void isEqual(int num, int value, int points) {
  460. currmaxgrade+=points;
  461. if (num == value) {
  462. printf("%s PASSED!n%s", KGRN, KNRM);
  463. grade+=points;
  464. } else {
  465. printf("%s NOT PASSED!n got: %d == %d %sn", KRED, num, value, KNRM);
  466. }
  467. }
  468.  
  469. void isEqual_long(unsigned long long num, unsigned long long value, int points) {
  470. currmaxgrade+=points;
  471. if (num == value) {
  472. printf("%s PASSED!n%s", KGRN, KNRM);
  473. grade+=points;
  474. } else {
  475. printf("%s NOT PASSED!n got: %llu == %llu %sn", KRED, num, value, KNRM);
  476. }
  477. }
  478.  
  479.  
  480. void isNotEqual(int num, int value, int points) {
  481. currmaxgrade+=points;
  482. if (num != value) {
  483. printf("%s PASSED!n%s", KGRN, KNRM);
  484. grade+=points;
  485. } else {
  486. printf("%s NOT PASSED!n got: %d != %d %sn",KRED, num, value, KNRM);
  487. }
  488. }
  489.  
  490. void isLesserThan(int num, int value, int points) {
  491. currmaxgrade+=points;
  492. if (num < value) {
  493. printf("%s PASSED!n%s", KGRN, KNRM);
  494. grade+=points;
  495. } else {
  496. printf("%s NOT PASSED!n got: %d < %d %sn",KRED, num, value, KNRM);
  497. }
  498. }
  499.  
  500. /* because floating points ops are not commutative nor associative */
  501. void isNear(float num, float value, int decimals, int points){
  502. currmaxgrade+=points;
  503. float diff = fabs(num - value);
  504. /* check for nearest integers */
  505. if (diff <= pow(10,(-decimals))) {
  506. printf("%s PASSED!n%s", KGRN, KNRM);
  507. grade+=points;
  508. }else {
  509. printf("%s NOT PASSED!n got: %f , expecting %f %sn",KRED, num, value, KNRM);
  510. }
  511. }
  512.  
  513.  
  514.  
  515. #endif //_SIMPLETEST_H
  516.  
  517. CC=gcc
  518.  
  519. CFLAGS=-Wall -Wextra -O0 -g -std=c11 -pthread #-Werror para versao final
  520. LDFLAGS=-lm
  521.  
  522. .PHONY: all
  523.  
  524. all: grade
  525.  
  526. priothreads.o: priothreads.h priothreads.c
  527. $(CC) $(CFLAGS) -c priothreads.c
  528.  
  529. test: priothreads.o test.c
  530. $(CC) $(CFLAGS) -o test priothreads.o test.c $(LDFLAGS)
  531.  
  532. grade: test
  533. ./test
  534.  
  535. clean:
  536. rm -rf *.o test
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement