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

Commit

Permalink
Re-implementate StateToTerminate e RemoveProgeny #12
Browse files Browse the repository at this point in the history
Fix Syscall 3 #19
Fix semafori su handler interrupt #20
  • Loading branch information
jjak0b committed May 7, 2020
1 parent a60c750 commit 1d42b6f
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 108 deletions.
9 changes: 0 additions & 9 deletions include/pcb/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,3 @@
* @param new_parent il nuovo genitore dei figli
*/
void pcb_SetChildrenParent( pcb_t* old_parent, pcb_t* new_parent );

/**
* @brief Dealloca dopo aver rimosso il descrittore fornito e tutta la sua progenie dalla queue della sentinella fornita
* @PostCondition Non avviene alcuna rimozione nella lista dei fratelli e del padre di p.
*
* @param p descrittore del processo da cui partire a rimuovere la progenie
* @param head queue in cui deve essere rimosso p e tutta la sua progenie
*/
void pcb_RemoveProgenyQ( pcb_t* p, struct list_head *head );
16 changes: 8 additions & 8 deletions include/scheduler/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,18 @@ int scheduler_StateToReady();
int scheduler_StateToWaiting( int* semKey );

/**
* @brief Dealloca il descrittore del processo che era in esecuzione, rimuovendo eventualmente la sua progenie
*
* @brief Dealloca il descrittore del processo associato al pid fornito, rimuovendo eventualmente la sua progenie
* @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
* @return int
* * 1 se non c'è alcun processo tracciato dallo scheduler in esecuzione
* * 1 se pid == NULL e non c'è alcun processo tracciato dallo scheduler in esecuzione
* * 0 altrimenti se è avvenuto tutto correttamente
* @param b_flag_terminate_progeny Se TRUE rimuove e dealloca dalla ready queue il descrittore del processo in esecuzione e tutta la sua progenie,
* @param pid identificatore del processo da terminare, se == NULL sarà considerato il processo attualmente in esecuzione
* @param b_flag_terminate_progeny Se TRUE rimuove e dealloca dalla ready queue o dalla semd wait queue il descrittore del processo in esecuzione e tutta la sua progenie,
* Se FALSE rimuove e dealloca solo il descrittore in esecuzione, ma tutti i suoi figli non avranno padre e ogni figlio non avrà fratelli
* cioè saranno indipendenti tra loro
*/
int scheduler_StateToTerminate( int b_flag_terminate_progeny );
int scheduler_StateToTerminate( pcb_t* pid, int b_flag_terminate_progeny );

/**
* @brief Restituisce il puntatore dell'attuale pcb_t in esecuzione
Expand Down Expand Up @@ -143,9 +143,9 @@ void scheduler_AddProcess( pcb_t *p );
int scheduler_RemoveProcess( pcb_t *p );

/**
* @brief wrapper di pcb_RemoveProgenyQ con passata la ready queue dello scheduler
* @PostCondition Se p è il processo in esecuzione allora viene deassociato nella struttura dello scheduler e deallocato.
* Non avviene alcuna rimozione nella lista dei fratelli e del padre di p.
* @brief Dealloca dopo aver rimosso il descrittore fornito e tutta la sua progenie dalla ready queue o dalla wait queue del semaforo associato al pcb
* Non avviene alcuna rimozione nella lista dei fratelli e del padre di p.
* @PostCondition Se p o uno della sua progenie è il processo in esecuzione allora viene deassociato nella struttura dello scheduler e deallocato anche esso.
*
* @param p descrittore del processo da cui partire a rimuovere la progenie
* @return int
Expand Down
51 changes: 10 additions & 41 deletions src/handler/shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ word Syscaller( state_t *state, word sysNo, word param1, word param2, word param
else {
b_hasReturnValue = TRUE;
*returnValue = -1;
scheduler_StateToTerminate( FALSE );
scheduler_StateToTerminate( NULL, FALSE );
}
break;
}
Expand Down Expand Up @@ -129,41 +129,8 @@ int Sys2_CreateProcess( state_t *child_state, int child_priority, pcb_t **child_
}

int Sys3_TerminateProcess( pcb_t *pid ) {
scheduler_t *s = scheduler_Get();

if ( pid ) {
if ( outProcQ( &s->ready_queue, pid ) == NULL )
return (-1); /* se il PCB non esiste ritorna errore */
}
else
pid = scheduler_GetRunningProcess();

/* ogni processo figlio viene rimosso da un'eventuale coda di blocco su semaforo */
struct list_head *child_iter;
pcb_t *dummy;


list_for_each( child_iter, &pid->p_child ) {
dummy = container_of( child_iter, pcb_t, p_sib );
int *key = dummy->p_semkey;
if ( key ) {
list_del( &dummy->p_next ); /* rimozione del PCB dalla coda dei processi bloccati */

/* aumento del valore del semaforo. se positivo si risveglia il primo in coda */
*key += 1;
if ( *key > 0 )
scheduler_AddProcess( removeBlocked( key ) );
}
}

/* se il processo da terminare è quello corrente, si passa il lavoro allo scheduler;
altrimenti il relativo pcb viene tolto dalla ready queue e inserito nella lista free */
if ( pid == scheduler_GetRunningProcess() )
scheduler_StateToTerminate( TRUE );
else
freePcb( outProcQ( &s->ready_queue, pid ) );

return 0;
int b_error = scheduler_StateToTerminate( pid, TRUE );
return ( b_error ? -1 : 0 );
}

void Sys4_Verhogen( int* semaddr ) {
Expand All @@ -172,11 +139,12 @@ void Sys4_Verhogen( int* semaddr ) {
}

void Sys5_Passeren( int* semaddr ) {
int status = semaphore_P( semaddr, scheduler_GetRunningProcess() );
pcb_t *pid = scheduler_GetRunningProcess();
int status = semaphore_P( semaddr, pid );
// nel caso ritornasse 1 non può accadere perchè ad ogni processo può essere nella ASL al massimo 1 volta
// infatti se non fosse disponibile un semd, non esisterebbe neanche questo processo
if( status == 1 ) {
scheduler_StateToTerminate( FALSE );
scheduler_StateToTerminate( pid, FALSE );
}
}

Expand All @@ -186,10 +154,11 @@ void Sys6_DoIO( word command, word *devregAddr, int subdevice ) {
device_GetInfo( devreg, &devLine, &devNo );

int *semKey = device_GetSem( devLine, devNo, subdevice );
pcb_t *pid = scheduler_GetRunningProcess();
// un semaforo di un device è sempre almeno inizializzato a 0, e quindi è sempre sospeso
int b_error = semaphore_P( semKey, scheduler_GetRunningProcess() );
int b_error = semaphore_P( semKey, pid );
if( b_error ) {
scheduler_StateToTerminate( FALSE );
scheduler_StateToTerminate( pid, FALSE );
}

if( devLine == IL_TERMINAL ) {
Expand All @@ -211,7 +180,7 @@ int Sys7_SpecPassup( state_t* currState, int type, state_t *old_area, state_t *n
return 0;
}

scheduler_StateToTerminate( FALSE );
scheduler_StateToTerminate( NULL, FALSE );
return -1;
}

Expand Down
19 changes: 15 additions & 4 deletions src/handler/umps/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,19 @@ void handle_irq(unsigned int line, unsigned int dev){
(line==IL_TERMINAL) ? handle_irq_terminal(dev_reg) : handle_irq_other_dev(dev_reg);

int *sem = device_GetSem(line, dev, GET_SEM_OFFSET(dev_reg, line)); /*sem associated with device*/
pcb_t *p = semaphore_V(sem);
if(p != NULL){
p->p_s.reg_v0 = dev_status;
}
pcb_t *p = NULL;

/*
Rispode a tutti i processi in attesa, con lo stesso stato.
Lo status probabilmente andrà in collisione con gli altri se sono > 1
ora come ora il processo che manda il comando non aspetta che il terminale sia pronto,
a meno che si gestito da un semaforo di livello superiore ( tramite syscall )
*/

do {
p = semaphore_V(sem);
if(p != NULL){
p->p_s.reg_v0 = dev_status;
}
} while( p != NULL && *sem < 0 );
}
29 changes: 0 additions & 29 deletions src/pcb/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,3 @@ void pcb_SetChildrenParent( pcb_t* old_parent, pcb_t* new_parent ) {
}
}
}

void pcb_RemoveProgenyQ( pcb_t* p, struct list_head *head ) {
if( p == NULL )
return;

/**
* Aggiunge ricorsivamente i figli di ogni processo ad uno stack di lavoro
* e poi elimina il padre sia dalla queue
* che dallo stack stesso, con conseguente deallocazione
*/
LIST_HEAD( pcb_stack );
list_add( &p->p_next, &pcb_stack );

while( !list_empty( &pcb_stack ) ) {
struct list_head *it_parent = list_next( &pcb_stack );
pcb_t *parent = container_of( it_parent, pcb_t, p_next );
while( !emptyChild( parent ) ){
pcb_t* child = removeChild( parent );

if( head != NULL ){
outProcQ( head, parent );
}

list_add( &child->p_next, &pcb_stack );
}
list_del( &parent->p_next );
freePcb( parent );
}
}
93 changes: 77 additions & 16 deletions src/scheduler/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,36 +110,97 @@ int scheduler_StateToWaiting( int* semKey ) {
}
}

int scheduler_StateToTerminate( int b_flag_terminate_progeny ) {
if( scheduler->running_p == NULL ) {
/**
* @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;

if( p == scheduler->running_p ) {
scheduler->running_p = NULL;
scheduler->b_force_switch = TRUE;
removed = p;
}
/* Rimuovo dalla wait queue V() */
else if( p->p_semkey != NULL) {
removed = outBlocked( p );
if( removed != NULL ) {
++(*p->p_semkey);
removed->p_semkey = NULL;
}
}
/* Rimuovo dalla ready queue */
else if( removed == NULL ) {
removed = outProcQ( &(scheduler->ready_queue), p );
}
}

int scheduler_StateToTerminate( pcb_t *pid, int b_flag_terminate_progeny ) {
if( pid == NULL ) {
pid = scheduler->running_p;
}

if( pid == NULL ) {
return 1;
}
/* Lo scollego dal padre */
outChild( pid );

if( b_flag_terminate_progeny ) {
/* rimuove la progenie dalla ready queue, poi dealloca e disassocia puntatore */
scheduler_RemoveProgeny( scheduler->running_p );
scheduler_RemoveProgeny( pid );
}
else {
pcb_SetChildrenParent( scheduler->running_p, NULL );
freePcb( scheduler->running_p );
scheduler->running_p = NULL;
scheduler->b_force_switch = TRUE;
scheduler_RemoveProcessFromAnyQ( pid );
pcb_SetChildrenParent( pid, NULL );
freePcb( pid );
}

return 0;
}

int scheduler_RemoveProgeny( pcb_t* p ) {
if( p == NULL ) {
return 1;
}
else if( scheduler->running_p == p ) {
scheduler->running_p = NULL; /* Rimuovo il tracciante di questo descrittore attivo */
scheduler->b_force_switch = TRUE;
}
/*
* asl::outChildBlocked sarebbe inefficiente -
* dovrei processare se stessa, e visitare nuovamente l'intero albero di processi per fare V() e rimuovere ogni PCB
*/

if( p == NULL )
return 1;

LIST_HEAD( pcb_stack );
pcb_t
*parent = p;

/*
* Ricorsivamente per ogni processo figlio dell intero albero:
* Ogni processo rimuove da una coda i figli e li aggiunge ad uno stack di lavoro
* e poi elimina il padre appena elaborato dallo stack per deallocarlo
*/

scheduler_RemoveProcessFromAnyQ( parent );
list_add( &p->p_next, &pcb_stack );

while( !list_empty( &pcb_stack ) ) {
struct list_head *it_parent = list_next( &pcb_stack );
parent = container_of( it_parent, pcb_t, p_next );

/* Aggiungo i figli sullo stack */
while( !emptyChild( parent ) ){
pcb_t* child = removeChild( parent );

pcb_RemoveProgenyQ( p, &scheduler->ready_queue );
/* Devo elaborarlo qui altrimenti poco dopo lo "stacco" dalla lista in cui risiede */
scheduler_RemoveProcessFromAnyQ( child );

list_add( &child->p_next, &pcb_stack );
}

/* Elimino il genitore */
list_del( &parent->p_next );
freePcb( parent );
}
return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion src/utilities/semaphore.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ pcb_t *semaphore_V( int *semkey ) {
pcb_t *p = NULL;
if( ++(*semkey) <= 0 ) {
p = removeBlocked( semkey );
if( p != NULL )
if( p != NULL ){
p->p_semkey = NULL;
scheduler_AddProcess( p );
}
}
return p;
}

0 comments on commit 1d42b6f

Please sign in to comment.