Commit dd4e7f99 authored by Michele Porta's avatar Michele Porta

Carica un nuovo file

parent 2b6cd5ac
//Stefano Cavalli 289341
//Michele Porta 289672
#ifdef MULTIPROC
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include "task.h"
#include "executive.h"
#include "monitor.h"
#define QUANTO_TEMPORALE 10 //il quanto di tempo che settiamo
#define FLAG_APERIODICO_OFF 0
#define FLAG_APERIODICO_ON 1
#define PRIORITA_AP 1
#define INDICE_AP_TASK 0
task_monitor* monitor;
task_monitor* monitor_aperiodic;
pthread_mutex_t mutex_executive; //mutex utilizzato dall'executive
int flag_task_ap; //definisco il flag del task aperiodico che mi servirà dopo
void gestione_deadline(){
//Se trovo un task che é in WORKING che manca la deadline lo lascio andare andare mentre tutti gli altri che vengono dopo nel frame vengono killati
int count;
for(count=0;count<NUM_P_TASKS;count++){
if(monitor->stato[count] == WORKING){
printf("Il task numero %d ha mancato la deadline, DEADLINE MISS!\n", count);
}
else if(monitor->stato[count] == PENDING){
printf("Viene killato il task: %d\n", count);
set_stato(monitor, IDLE, count);
}
}
}
void* p_task_handler(void* arg)
{
int indice_task = *(int*)arg;
while(1){
wait_monitor(monitor, indice_task);
//Inizia l'esecuzione del task
(*P_TASKS[indice_task])();
//Termina l'esecuzione del task
}
}
void* ap_task_handler(void* arg)
{
//funziona come il p_task_handler
while(1){
wait_monitor(monitor_aperiodic, INDICE_AP_TASK);
printf("Avvio esecuzione task aperiodico\n");
(*AP_TASK)();
printf("Interrotta esecuzione task aperiodico\n");
}
}
void ap_task_request()
{
pthread_mutex_lock(&mutex_executive);
flag_task_ap = FLAG_APERIODICO_ON;
pthread_mutex_unlock(&mutex_executive);
}
void* executive(void* arg)
{
int i = 0;
int indice_frame = 0;
//passo i thread come parametri alle variabili
pthread_t* task_threads = (pthread_t *) arg;
pthread_cond_t condizione;
pthread_cond_init( &condizione, NULL );
// Strutture per il risveglio dell'executive
struct timespec time;
struct timeval utime;
gettimeofday(&utime,NULL);
time.tv_sec = utime.tv_sec;
time.tv_nsec = utime.tv_usec * 1000;
struct sched_param sched;
while(1)
{
pthread_mutex_lock(&mutex_executive);
printf("\n");
printf("------------------------------------------------------------------------\n");
printf("\n");
gestione_deadline();
// Gestione delle richieste dei task aperiodici
if(flag_task_ap == FLAG_APERIODICO_ON){
printf("É arrivato il task APERIODICO\n");
flag_task_ap = FLAG_APERIODICO_OFF;
//Se il task AP é già in esecuzione va in Deadline Miss
if(get_stato(monitor_aperiodic, INDICE_AP_TASK) != IDLE){
printf("Il task APERIODICO ha mancato la deadline! Non viene eseguito nel prossimo frame\n");
}
else{
set_stato(monitor_aperiodic, PENDING, INDICE_AP_TASK);
pthread_cond_signal(&monitor_aperiodic->cond[INDICE_AP_TASK]);
}
}
sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
i = 0;
printf("Inizio del frame %d\n", indice_frame);
while( SCHEDULE[indice_frame][i] != -1 ){
sched.sched_priority = sched.sched_priority - i;
//imposto prioritá decrescenti
pthread_setschedparam( task_threads[SCHEDULE[indice_frame][i]], SCHED_FIFO, &sched);
set_stato(monitor, PENDING, SCHEDULE[indice_frame][i]);
pthread_cond_signal( &monitor->cond[SCHEDULE[indice_frame][i]]);
printf("Esecuzione del task: %d\n", SCHEDULE[indice_frame][i]);
i++;
}
indice_frame = (indice_frame + 1) % NUM_FRAMES;
time.tv_sec += ( time.tv_nsec + ( H_PERIOD * QUANTO_TEMPORALE / NUM_FRAMES ) * 1000000 ) / 1000000000;
time.tv_nsec = ( time.tv_nsec + ( H_PERIOD * QUANTO_TEMPORALE / NUM_FRAMES ) * 1000000 ) % 1000000000;
//L'executive é in attesa sul suo mutex
pthread_cond_timedwait( &condizione, &mutex_executive, &time );
pthread_mutex_unlock(&mutex_executive);
}
}
void threads_create(){
pthread_attr_t thread_attr;
struct sched_param sched;
pthread_t thread_executive;
pthread_t thread_aperiodic;
pthread_t task_threads[NUM_P_TASKS];
int param[NUM_P_TASKS];
int i;
pthread_attr_init( &thread_attr );
pthread_attr_setinheritsched( &thread_attr, PTHREAD_EXPLICIT_SCHED );
pthread_attr_setschedpolicy( &thread_attr, SCHED_FIFO );
#ifdef MULTIPROC
//Se siamo in presenza di multiprocessore forzo all'utilizzo di una sola CPU
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(0, &cpuset);
pthread_attr_setaffinity_np( &thread_attr, sizeof(cpu_set_t), &cpuset );
#endif
// Creazione del task aperiodico con priorità minore di tutti i thread e dell'executive
sched.sched_priority = PRIORITA_AP ;
pthread_attr_setschedparam( &thread_attr, &sched );
if( pthread_create( &thread_aperiodic, &thread_attr, &ap_task_handler, NULL) != 0){
fprintf(stderr, "Errore: Ci vuole SUDO!\n");
exit(-1);
}
// Creazione dei thread con priorità iniziale minore di quella dell'executive
sched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
pthread_attr_setschedparam( &thread_attr, &sched );
for( i = 0; i < NUM_P_TASKS; i++ ){
// i rappresenta l'indice del task da eseguire
param[i] = i;
if ( pthread_create( &task_threads[i], &thread_attr , &p_task_handler, &param[i]) != 0 ){
fprintf( stderr, "Errore: Impossibile creare il Task.\n" );
exit(-1);
}
}
// Creazione executive con la priorità massima
sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_setschedparam( &thread_attr, &sched );
if ( pthread_create( &thread_executive, &thread_attr, &executive, task_threads) != 0 ){
fprintf( stderr, "Errore: Impossibile creare il Task.\n" );
exit(-1);
}
//Non vogliamo che l'executive termini
pthread_join(thread_executive, NULL);
}
// Deallocazione della memoria
void destroy(){
pthread_mutex_destroy(&mutex_executive);
monitor_destroy(monitor, NUM_P_TASKS);
monitor_destroy(monitor_aperiodic, 1);
task_destroy();
}
int main(int argc, char** argv){
pthread_mutex_init( &mutex_executive, NULL );
// Inizializzazione dei task
task_init();
// Allocazione della memoria per le variabili globali
monitor = malloc(sizeof(task_monitor));
monitor_aperiodic = malloc(sizeof(task_monitor));
// Inizializzazione monitor
init_monitor(monitor, NUM_P_TASKS);
init_monitor(monitor_aperiodic, 1);
// Inizializzazione flag per il task aperiodico
flag_task_ap = FLAG_APERIODICO_OFF;
// Creazione thread e avvio routine
threads_create();
// Deallocazione memoria
destroy();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment