//gestore degli interrupt per i terminali void terminal_interrupt(){ termreg_t *dev_t; int i ; memaddr *interrupt_line = (memaddr*) CDEV_BITMAP_ADDR(IL_TERMINAL); //ottengo la linea di interrupt per i terminali int dev_num = pending_interrupt_device(interrupt_line); //ottengo il terminale su cui pende l'interrupt dev_t = (termreg_t*) DEV_REG_ADDR(IL_TERMINAL, dev_num); //ottengo il registro del terminale unsigned int status ; //valore da far ritornare alla SYS8 status_iprint = dev_t->transm_status; if( (dev_t->transm_status & DEV_TERM_STATUS ) == DEV_TTRS_S_CHARTRSM){ //trattasi di una scrittura, priorità più alta della lettura status = dev_t->transm_status; i = devSemIndex(IL_TERMINAL+1, dev_num); dev_t->transm_command = DEV_C_ACK; //acknowledgement if( devSem[i] < 1 ){ //se ci sono dei processi bloccati sul semaforo verhogen(&devSem[i], 1, status, getTODLO() - interruptStart); //li libero e passo loro lo status register devStatus[i] = 0; } else{ //se nessuno sta aspettando l'interrupt salvo lo status register per quando qualcuno lo richiederà devStatus[i] = dev_t->transm_status; interruptTime[i] = getTODLO() - interruptStart; //tempo impegato a gestire l'interrupt } } else if( (dev_t->recv_status & DEV_TERM_STATUS) == DEV_TRCV_S_CHARRECV ){ //trattasi di una lettura status = dev_t->recv_status; i = devSemIndex(IL_TERMINAL, dev_num); dev_t->recv_command = DEV_C_ACK; //acknowledgement if( devSem[i] < 1 ){ verhogen(&devSem[i], 1,status, getTODLO() - interruptStart); //come sopra devStatus[i] = 0; } else{ devStatus[i] = dev_t->recv_status; interruptTime[i] = getTODLO() - interruptStart; //tempo impegato a gestire l'interrupt } } }
/** @brief This function handles a system call request coming from a process running in Kernel Mode. @return Void. */ HIDDEN void syscallKernelMode() { /* Identify and handle the system call */ switch (SYSBP_Old->a1) { case CREATEPROCESS: CurrentProcess->p_s.a1 = createProcess((state_t *) SYSBP_Old->a2); break; case TERMINATEPROCESS: terminateProcess(); break; case VERHOGEN: verhogen((int *) SYSBP_Old->a2); break; case PASSEREN: passeren((int *) SYSBP_Old->a2); break; case GETCPUTIME: CurrentProcess->p_s.a1 = getCPUTime(); break; case WAITCLOCK: waitClock(); break; case WAITIO: CurrentProcess->p_s.a1 = waitIO((int) SYSBP_Old->a2, (int) SYSBP_Old->a3, (int) SYSBP_Old->a4); break; case SPECTRAPVEC: specTrapVec((int) SYSBP_Old->a2, (state_t *) SYSBP_Old->a3, (state_t *) SYSBP_Old->a4); break; default: /* Distinguish whether SYS5 has been invoked or not */ checkSYS5(SYSBK_EXCEPTION, SYSBP_Old); } /* Call the scheduler */ scheduler(); }
//gestore degli interrupt void int_handler(){ interruptStart = getTODLO(); //tempo in cui comincia la gestione dell'interrupt, da //assegnare poi ad un eventuale processo svegliato dall'interrupt state_t *returnState = (state_t*) INT_OLDAREA; returnState->pc -= 4; if( current_process != NULL){ copy_state( returnState, ¤t_process->p_s ); current_process->userTime += interruptStart - userTimeStart;//se c'è un processo aggiorno il suo userTime current_process->CPUTime += interruptStart - CPUTimeStart; } int cause = getCAUSE(); if(CAUSE_IP_GET(cause, IL_TIMER)){ if( current_timer == PSEUDO_CLOCK ){ while( devSem[CLOCK_SEM] < 0 ){ //Ad ogni pseudo clock tick mi assicuro che il semaforo sia sempre a zero verhogen( &devSem[CLOCK_SEM], 1, 0, getTODLO() - interruptStart); } } else if(current_timer == TIME_SLICE ){ if( current_process != NULL ){ insertProcQ( priority_queue(current_process->priority), current_process); current_process->CPUTime += getTODLO() - interruptStart; //se metto in pausa il processo aggiorno anche il suo CPUTime current_process = NULL; } } } else if(CAUSE_IP_GET(cause, IL_DISK)){ dtnp_interrupt(IL_DISK); } else if(CAUSE_IP_GET(cause, IL_TAPE)){ dtnp_interrupt(IL_TAPE); } else if(CAUSE_IP_GET(cause, IL_ETHERNET)){ dtnp_interrupt(IL_ETHERNET); } else if(CAUSE_IP_GET(cause, IL_PRINTER)){ dtnp_interrupt(IL_PRINTER); } else if(CAUSE_IP_GET(cause, IL_TERMINAL)){ terminal_interrupt(); } scheduler(); }
//disk, tape, network, printer interrupt handler void dtnp_interrupt(int int_line){ dtpreg_t *dev_g; int i; unsigned int status; //valore da far ritornare alla SYS8 memaddr *interrupt_line = (memaddr*) CDEV_BITMAP_ADDR(int_line); //ottengo la linea di interrupt int dev_num = pending_interrupt_device(interrupt_line); //ottengo il device su cui pende l'interrupt dev_g = (dtpreg_t*) DEV_REG_ADDR(int_line, dev_num); dev_g->command = DEV_C_ACK; //passo l'acknowledgement i = devSemIndex(int_line, dev_num) ; if( devSem[i] < 1 ){ //se ci sono dei processi bloccati sul semaforo status = dev_g->status; //li libero e passo loro lo status register e il tempo di gestione verhogen( &devSem[i] , 1 , status, getTODLO() - interruptStart); devStatus[i] = 0; } else{ //se nessuno sta aspettando l'interrupt salvo lo status register e il tempo di gestione dell'interrupt // per quando qualcuno li richiederà devStatus[i] = dev_g->status; interruptTime[i] = getTODLO() - interruptStart; } }
void sysBpHandler(){ saveStateIn(sysbp_old, ¤tProcess->p_s); unsigned int cause = CAUSE_EXCCODE_GET(sysbp_old->CP15_Cause); unsigned int a0 = (*sysbp_old).a1; unsigned int a1 = (*sysbp_old).a2; unsigned int a2 = (*sysbp_old).a3; unsigned int a3 = (*sysbp_old).a4; /* Se l'eccezione è di tipo System call */ if(cause==EXC_SYSCALL){ /* Se il processo è in kernel mode gestisce adeguatamente */ if( (currentProcess->p_s.cpsr & STATUS_SYS_MODE) == STATUS_SYS_MODE){ /* Se è fra SYS1 e SYS8 richiama le funzioni adeguate */ switch(a0){ case CREATEPROCESS: createProcess((state_t *) a1); break; case TERMINATEPROCESS: terminateProcess(currentProcess); break; case VERHOGEN: verhogen((int *) a1); break; case PASSEREN: passeren((int *) a1); break; case SPECTRAPVEC: specExStVec((int) a1, (state_t *) a2, (state_t *) a3); break; case GETCPUTIME: getCPUTime(); break; case WAITCLOCK: waitForClock(); break; case WAITIO: waitForIO((int) a1, (int) a2, (int) a3); break; /* Altrimenti la gestione viene passata in alto */ default: useExStVec(SPECSYSBP); break; } /* Richiamo lo scheduler */ scheduler(); /* Se invece è in user mode */ } else if((currentProcess->p_s.cpsr & STATUS_USER_MODE) == STATUS_USER_MODE){ /* Se è una system call */ if(a0 >= CREATEPROCESS && a0 <= WAITIO){ /* Gestisco come fosse una program trap */ saveStateIn(sysbp_old, pgmtrap_old); /* Setto il registro cause a Reserved Instruction */ pgmtrap_old->CP15_Cause = CAUSE_EXCCODE_SET(pgmtrap_old->CP15_Cause, EXC_RESERVEDINSTR); /* Richiamo l'handler per le pgmtrap */ pgmHandler(); } else { useExStVec(SPECSYSBP); } } /* Altrimenti se l'eccezione è di tipo BreakPoint */ } else if(cause == EXC_BREAKPOINT){ useExStVec(SPECSYSBP); } PANIC(); }