Skip to content
This repository has been archived by the owner on Nov 2, 2022. It is now read-only.

Commit

Permalink
Aggiunto processo idle se tutti i processi sono in wait queue #12
Browse files Browse the repository at this point in the history
Fix selezione del giusto semaforo in device_GetSem
Aggiustamento semafori
  • Loading branch information
jjak0b committed May 13, 2020
1 parent 0dbf06b commit 0c384d7
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 45 deletions.
2 changes: 2 additions & 0 deletions include/pcb/pcb.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ void insertChild(pcb_t *prnt, pcb_t *p);
pcb_t *removeChild(pcb_t *p);
pcb_t *outChild(pcb_t *p);

/* Inizializza un singolo pcb con valori NULL/0 e liste vuote */
void pcb_init( pcb_t *p );
#endif
12 changes: 9 additions & 3 deletions include/scheduler/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ struct scheduler_t {
/* booleano indicante se il processo attuale non può continuare lo scheduling (TRUE) oppure continuare mantenere il processo schedulato (FALSE) */
int b_force_switch;

/* Pcb utilizzato per mettere la macchina in stato di idle */
pcb_t idlePcb;
int b_has_idle;

};
typedef struct scheduler_t scheduler_t;

Expand Down Expand Up @@ -92,15 +96,17 @@ int scheduler_StateToReady();
/**
* @brief aggiunge il processo corrente alla ASL con associato la chiave fornita
*
* @PreCondition Prima di chiamare questa funzione, è necessario chiamare scheduler_UpdateContext() per aggiornare il contesto del processo attuale
* @PostCondition Dopo questo stato è necessario richiamare scheduler_schedule per procedere con la schedulazione dei processi
* @PreCondition Prima di chiamare questa funzione, è necessario chiamare scheduler_UpdateContext() per aggiornare il contesto del processo attuale.
* Inoltre il processo deve essere nella ready queue oppure o deve essere il processo in esecuzione
* @PostCondition se p == NULL sarà preso in considerazione il processo corrente. Dopo questo stato è necessario richiamare scheduler_schedule per procedere con la schedulazione dei processi
* @param semKey chiave da associare al semaforo
* @param p processo da sospendere sulla coda del semaforo
* @return int
* * -1 se nessun processo è attualmente assegnato come processo corrente
* * 0 se l'operazione è stata effettuata correttamente
* * 1 se non è stato possibile aggiungere il processo corrente alla ASL (impossibile allocare semaforo)
*/
int scheduler_StateToWaiting( int* semKey );
int scheduler_StateToWaiting( pcb_t* p, int* semKey );

/**
* @brief Dealloca il descrittore del processo associato al pid fornito, rimuovendo eventualmente la sua progenie
Expand Down
21 changes: 19 additions & 2 deletions include/system/shared/device/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,14 @@
//
#define GET_SEM_OFFSET(dev_reg,line) (line!=IL_TERMINAL ? (0) : (IS_TERM_READY(dev_reg->term.transm_status)? (0) : (1)))
//
#define GET_SEM_INDEX(dev_reg,line,device) (N_DEV_PER_IL*(line-N_EXT_IL+GET_SEM_OFFSET(dev_reg,line))+device)
#define GET_SEM_INDEX_SUBDEV(line,device,subdevice) (N_DEV_PER_IL*(line-N_EXT_IL+ ( line!=IL_TERMINAL ? 0 : subdevice ) )+device)
#define GET_SEM_INDEX(dev_reg,line,device) (N_DEV_PER_IL*(line-DEV_IL_START+GET_SEM_OFFSET(dev_reg,line))+device)
/*
matrice vettorizzata in righe x colonne
riga i: semafori della stessa (i-DEV_IL_START)-esima interrupt line
(riga i+s: semafori della stessa interrupt line ma contenente i s-esimi dei subdevice )
colonna j: semaforo dell j-esimo device di un interrupt line
*/
#define GET_SEM_INDEX_SUBDEV(line,device,subdevice) (N_DEV_PER_IL*(line - DEV_IL_START + ( line!=IL_TERMINAL ? 0 : subdevice ) )+device)
//
#define GET_DEV_STATUS(dev_reg, line) (line!=IL_TERMINAL ?(dev_reg->dtp.status):(GET_SEM_OFFSET(dev_reg,line) ?(dev_reg->term.recv_status):(dev_reg->term.transm_status)) )

Expand All @@ -63,6 +69,17 @@ void device_GetInfo( devreg_t *devreg, int *devline, int *devNo );
*/
int *device_GetSem( int devline, int devNo, int subDev );

/**
* @brief indica se ci sono processi in attesa su qualche coda di un semaforo associata ad un device
*
* @PostCondition se sem == NULL saranno controllati tutti i semafori dei device, invece che solo su sem
* @param sem
* @return int
* - TRUE se c'è almeno un processo in attesa
* - FALSE altrimenti
*/
int device_IsAnyProcessWaiting( int *sem );

#endif


6 changes: 3 additions & 3 deletions include/utilities/semaphore.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
* @brief Decrementa il valore del semaforo, se diventa < 0, allora il processo indicato viene sospeso;
* cioè rimosso dalla ready queue dello scheduler e posto in attesa sulla coda del semaforo specificato
* @PreCondition semkey != NULL
*
* @PostCondition se p == NULL, sarà preso in considerazione il processo corrente
* @param semkey
* @param p
* @return int
* FALSE se è stato sospeso correttamente
* TRUE se p == NULL oppure se non è stato possibile allocare un semd per il processo specificato
* * 0 se è stato sospeso correttamente
* * !=0 se p == NULL e non c'è alcun processo in esecuzione, oppure se non è stato possibile allocare un semd per il processo specificato
*/
int semaphore_P( int *semkey, pcb_t * p );

Expand Down
2 changes: 1 addition & 1 deletion src/handler/shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ void Sys6_DoIO( word command, word *devregAddr, int subdevice ) {
// un semaforo di un device è sempre almeno inizializzato a 0, e quindi è sempre sospeso
if( *semKey >= 0 ){
if( devLine == IL_TERMINAL ) {
if( subdevice ) {
if( !subdevice ) {
devreg->term.transm_command = command;
}
else {
Expand Down
5 changes: 5 additions & 0 deletions src/p1.5test_bikaya_v0.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ void termprint(char *str) {
#define termprint(str) tprint(str);
#endif


// extern void print( char *msg );
// #undef termprint
// #define termprint(str) print(str);

char *toprint[] = {
"1 \n", "2 _nnnn_ \n", "3 dGGGGMMb \n",
"4 @p~qp~~qMb \n", "5 M|@||@) M| \n", "6 @,----.JM| \n",
Expand Down
14 changes: 11 additions & 3 deletions src/pcb/pcb.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,17 @@ void insertProcQ(struct list_head *head, pcb_t *p){
l’elemento rimosso.
*/
pcb_t *allocPcb(void){
pcb_t *new;
new = removeProcQ(pcbFree_h);
pcb_t *new = removeProcQ(pcbFree_h);
pcb_init( new );
return new;
}

/*
inizializza
tutti i campi (NULL/0)
e le liste come liste vuote
*/
void pcb_init( pcb_t *new ){
if(new != NULL){
//inizializzazione pcb
INIT_LIST_HEAD(&(new->p_child));
Expand Down Expand Up @@ -151,7 +160,6 @@ pcb_t *allocPcb(void){
new->p_s.TOD_Low = 0;
#endif
}
return new;
}

/* PCB QUEUE HANDLING */
Expand Down
84 changes: 64 additions & 20 deletions src/scheduler/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,38 @@
#include <pcb/utils.h>
#include <system/const.h>
#include <asl/asl.h>
#include <system/shared/device/device.h>
#include <system/shared/registers.h>

HIDDEN scheduler_t *scheduler;

/**
* @brief Rimuove il processo come processo corrente, altrimenti dalla wait queue, altrimenti ancora se non è presente lo rimuove dalla ready queue
* @PostCondition Se viene rimosso dalla wait queue di un semaforo, incrementa il valore del semaforo stesso, quindi il suo p_semkey diventa NULL
*
* @param p il processo da rimuovere
*/
void scheduler_RemoveProcessFromAnyQ( pcb_t *p );

void idle_entry(){ while( TRUE ) WAIT(); }

void scheduler_init() {
HIDDEN scheduler_t scheduler_struct; /* Tutte le funzioni di questo Header fanno riferimento implicito a questa struttura */
mkEmptyProcQ( &scheduler_struct.ready_queue );
scheduler_struct.running_p = NULL;

scheduler_struct.b_has_idle = FALSE;
pcb_t *idlePcb = &scheduler_struct.idlePcb;
pcb_init( idlePcb );
idlePcb->original_priority = DEFAULT_PRIORITY;
idlePcb->priority = idlePcb->original_priority;
SetStatus( &idlePcb->p_s, STATUS_NULL);
EnableInterrupts( &idlePcb->p_s, TRUE);
EnableKernelMode( &idlePcb->p_s, TRUE);
EnableVirtualMemory( &idlePcb->p_s, FALSE);
SetPC( &idlePcb->p_s, (memaddr)idle_entry );
SetSP( &idlePcb->p_s, RAM_TOP );

scheduler = &scheduler_struct;
}

Expand All @@ -51,12 +76,33 @@ void scheduler_DoAging() {

int scheduler_schedule( int b_force_switch ) {

if( scheduler->b_has_idle ) {
scheduler_RemoveProcessFromAnyQ( &scheduler->idlePcb );
scheduler->b_has_idle = FALSE;
}
int b_should_switch = b_force_switch || scheduler->b_force_switch || scheduler->running_p == NULL;

scheduler->b_force_switch = FALSE; /* resetto */

if( scheduler->running_p == NULL && emptyProcQ( &scheduler->ready_queue ) ) {
HALT();
/* tutti i processi potrebbero essere in attesa su una coda di qualche semaforo */

/* se non ci sono processi in attesa su qualche semaforo dei device,
allora o tutti i processi sono terminati oppure può essere deadlock */
if( !device_IsAnyProcessWaiting( NULL ) ) {
HALT();
}
/* altrimenti metto nella ready queue un processo che fa solo WAIT, mettendo il sitema in stato di idle */
else {
scheduler->b_force_switch = TRUE; /* preparo già per il prossimo scheduling, così in caso si sia riempita la ready queue, procede con cambiare processo */
b_should_switch = TRUE;

scheduler_AddProcess( &scheduler->idlePcb );
scheduler->b_has_idle = TRUE;
scheduler_StartProcessChronometer(); // giusto per non ottenere valori strani nelle tempistiche
}
}

if( b_should_switch ) {
scheduler_DoAging(); /* Incrementa priorità per evitare starvation dei processi */

Expand All @@ -75,17 +121,17 @@ int scheduler_schedule( int b_force_switch ) {
// TODO: Re-impostare time slice rimanente oppure ignorare ?
}


LDST( &scheduler->running_p->p_s ); /* mette in esecuzione il processo */
return -1;
}

void scheduler_UpdateContext( state_t* state ) {
if( scheduler->running_p != NULL )
if( scheduler->running_p != NULL ){
moveState( state, &scheduler->running_p->p_s );

scheduler_UpdateProcessRunningTime();
scheduler_StartProcessChronometer();
scheduler_UpdateProcessRunningTime();
scheduler_StartProcessChronometer();
}
}

int scheduler_StateToReady() {
Expand All @@ -104,23 +150,18 @@ int scheduler_StateToReady() {

}

int scheduler_StateToWaiting( int* semKey ) {
pcb_t* p = scheduler->running_p;
if( p == NULL ) {
return -1;
}
scheduler_StateToReady();
int scheduler_StateToWaiting( pcb_t *p, int* semKey ) {
if( p == NULL )
p = scheduler->running_p;
if( p == NULL ) return -1;

if( p == scheduler->running_p )
scheduler_StateToReady();
scheduler_RemoveProcess( p );
int b_result = insertBlocked( semKey, p );
return b_result;
}

/**
* @brief Rimuove il processo come processo corrente, altrimenti dalla wait queue, altrimenti ancora se non è presente lo rimuove dalla ready queue
* @PostCondition Se viene rimosso dalla wait queue di un semaforo, incrementa il valore del semaforo stesso, quindi il suo p_semkey diventa NULL
*
* @param p il processo da rimuovere
*/
void scheduler_RemoveProcessFromAnyQ( pcb_t *p ) {
pcb_t *removed = NULL;

Expand All @@ -147,7 +188,7 @@ int scheduler_StateToTerminate( pcb_t *pid, int b_flag_terminate_progeny ) {
if( pid == NULL ) {
pid = scheduler->running_p;
}

if( pid == NULL ) {
return 1;
}
Expand All @@ -160,7 +201,8 @@ int scheduler_StateToTerminate( pcb_t *pid, int b_flag_terminate_progeny ) {
else {
scheduler_RemoveProcessFromAnyQ( pid );
pcb_SetChildrenParent( pid, NULL );
freePcb( pid );
if( pid != &scheduler->idlePcb )
freePcb( pid );
}

return 0;
Expand Down Expand Up @@ -235,6 +277,8 @@ int scheduler_RemoveProcess( pcb_t *p ) {
void scheduler_StartProcessChronometer() {
pcb_t *p = scheduler->running_p; /* rende più leggibile il codice */

if( p == NULL ) return;

unsigned int *todlo = (unsigned int *) BUS_REG_TOD_LO;

p->chrono_start_tod = *todlo; /* il processo inizia la sua esecuzione in kernel mode */
Expand Down
14 changes: 14 additions & 0 deletions src/system/shared/device/device.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <system/system.h>
#include <system/shared/device/device.h>
#include <asl/asl.h>

HIDDEN int _semdev[SEM_DEV_N];

Expand Down Expand Up @@ -33,3 +34,16 @@ void device_GetInfo( devreg_t *devreg, int *_line, int *_devNo ) {
int *device_GetSem( int devline, int devNo, int subDev ) {
return &_semdev[ GET_SEM_INDEX_SUBDEV(devline, devNo, subDev) ];
}

int device_IsAnyProcessWaiting( int *sem ) {
if( sem != NULL ) {
return headBlocked( sem ) != NULL;
}

int i = 0;
while( i < SEM_DEV_N && _semdev[ i ] >= 0 )
i++;
/* se è arrivato in fondo, avrà indice uguale al numero dei semafori */

return i != SEM_DEV_N;
}
4 changes: 2 additions & 2 deletions src/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

void test_1_5();
void test_init(void){
test_1_5();
return;
// test_1_5();
// return;
pcb_t *test_pcb = allocPcb();
state_t *state = &(test_pcb->p_s);

Expand Down
13 changes: 2 additions & 11 deletions src/utilities/semaphore.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,9 @@
#include <pcb/pcb.h>

int semaphore_P( int *semkey, pcb_t * p ) {
int b_error = FALSE;
if( p == NULL )
return !b_error;

int b_error = 0;
if( --(*semkey) < 0 ) {
if( p == scheduler_GetRunningProcess() ){
b_error = scheduler_StateToWaiting( semkey );
}
else {
scheduler_RemoveProcess( p );
b_error = insertBlocked( semkey, p );
}
b_error = scheduler_StateToWaiting( p, semkey );
}
return b_error;
}
Expand Down

0 comments on commit 0c384d7

Please sign in to comment.