void useExStVec(int type){ if(currentProcess!=NULL) { /* Se ho già fatto spectrapvec per il tipo di eccezione*/ if (currentProcess->excStVec[type*2]!=NULL){ /* Salvo lo stato nella oldarea adeguata*/ switch(type){ case SPECTLB: saveStateIn(tlb_old, currentProcess->excStVec[type*2]); break; case SPECPGMT: saveStateIn(pgmtrap_old, currentProcess->excStVec[type*2]); break; case SPECSYSBP: saveStateIn(sysbp_old, currentProcess->excStVec[type*2]); break; } /* Carico lo stato dalla newarea */ LDST(currentProcess->excStVec[(type*2)+1]); }else{ /* Altrimenti tratto come una SYS2 */ terminateProcess(currentProcess); scheduler(); } } }
void scheduler() { //Due possibili casi: // -Esiste un processo in esecuzione -> context switch // -Non c'è un processo -> ne carico uno if(currentProcess!=NULL){ //current process è quello che deve essere eseguito timer+=getTODLO()-last_access; last_access=getTODLO(); //#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -> sta su uARMconst //#define SCHED_TIME_SLICE 5000 //#define SCHED_PSEUDO_CLOCK 100000 setTIMER(MIN(SCHED_TIME_SLICE, SCHED_PSEUDO_CLOCK-timer)); LDST(&(currentProcess->s_t)); } else{ //Anche qui due casi possibili, controlliamo se la readyQueue è vuota if(clist_empty(readyQueue)){ //processCount = 0 -> HALT -> non ci sono processi if(processCount == 0) HALT(); //processCount>0 e SBC==0-> qualcosa è andato storto -> deadlock if(processCount>0 && softBlockCount == 0) PANIC(); //caso "normale" -> aspettiamo che un processo necessiti di essere allocato if(processCount>0 && softBlockCount > 0) WAIT(); //qualsiasi altro stato PANIC(); } else{ //semplicemente carico il primo processo in memoria //scherzavo, non è semplice currentProcess = removeProcQ(readyQueue); if(currentProcess == NULL) PANIC(); //qualcosa è andato storto //imposta i timer e altre cose brutte scheduler(); } } }
/** Quando invocata, la sys8 esegue una P sul semaforo associato al device identificato da intNo, dnume e waitForTermRead Registro a1: linea di interrupt Registro a2: device number Registro a3: operazione di terminal read/write Registro v0: status del device */ void wait_for_io_device(void){ state_t* before = (state_t*)new_old_areas[getPRID()][SYSBK_OLD]; int line = before->reg_a1; int devno = before->reg_a2; int rw = before->reg_a3; _passeren((line*(devno+1)+20)+rw); before->reg_v0 = devstatus[line-3][devno+rw]; devstatus[line-3][devno+rw] = 0; LDST(before); }
void schedule() { /* azioni da compiere quando non c'e' nessun thread pronto ad eseguire */ if (emptyThreadQ(&readyQueue) && currentThread == NULL) { prova(); if (threadCount == 1)/* se c'e' solo il SSI -> normal system shutdown */ HALT(); /* chiamo la HALT ROM routine */ else if (threadCount > 0 && softBlockCount == 0) {/* deadlock */ PANIC(); /* chiamo la PANIC ROM routine */ } else if (threadCount > 0 && softBlockCount > 0) { /* in attesa di un interrupt -> wait state */ /* se ci sono thread in attesa dello pseudo tick, * carico il valore dello pseudo clock nel registro della cpu.*/ if (!emptyThreadQ(&waitForPseudoClockQueue)) { SET_IT(SCHED_PSEUDO_CLOCK); } /* impostiamo lo stato del processore con gli interrupt abilitati*/ setSTATUS(getSTATUS() | STATUS_IEc | STATUS_INT_UNMASKED); for (;;); } } else { /* Se non c'è nessun Thread in esecuzione ma c'e n'è almeno uno nella readyQueue allora carico un thread*/ if (currentThread == NULL) { currentThread = removeThread(&readyQueue); currentThread->elapsedTime = 0; currentThread->startTime = GET_TODLOW; SET_IT(SCHED_TIME_SLICE); /* Altrimenti se è passato il SCHED_TIME_SLICE rimuovo il thread corrente dall'esecuzione*/ } else if (currentThread->elapsedTime >= SCHED_TIME_SLICE) { //in questo modo do priorità all'SSI if (currentThread != tcb_SSI) { insertThread(&readyQueue, currentThread); /*Carico un nuovo thread*/ currentThread = removeThread(&readyQueue); } currentThread->elapsedTime = 0; currentThread->startTime = GET_TODLOW; /* Se e' scattato lo pseudo clock non settiamo il timer a 5 ms * dato che scattera' subito l'interrupt dello pseudo clock */ if (!isPseudoClock) SET_IT(SCHED_TIME_SLICE); } /* carico lo stato del thread nel processore dalla sua tcb */ LDST(&(currentThread->t_state)); } }
/** Quando invocata, la sys11 consente di definire gestori di SYS/BP Exception per il processo corrente. Registro a1: indirizzo della OLDArea in cui salvare lo stato corrente del processore. Registro a2: indirizzo della NEWArea del processore (da utilizzare nel caso si verifichi una SYS/BP Exception) */ void specify_sys_state_vector(void){ pcb_t* suspend = currentproc[getPRID()]; state_t* before = (state_t*)new_old_areas[getPRID()][SYSBK_OLD]; if ((suspend->handler[SYSBK+3] == NULL) && (suspend->handler[SYSBK] == NULL)){ suspend->handler[SYSBK+3] = (state_t*)before->reg_a1; suspend->handler[SYSBK] = (state_t*)before->reg_a2; LDST(&suspend->p_s); } else { kill(suspend); scheduler(); } }
/** Quando invocata, la sys5 esegue una P sul semaforo con chiave semKey. Registro a1: chiave del semaforo su cui effettuare la P. */ void passeren(void){ pcb_t* suspend = currentproc[getPRID()]; state_t* before = (state_t*)new_old_areas[getPRID()][SYSBK_OLD]; int semkey = before->reg_a1; semd_t* sem; while (!CAS(&mutex_semaphoreprova,0,1)); /* critical section */ sem = mygetSemd(semkey); sem->s_value--; if (sem->s_value >= 0){ /* GO! */ CAS(&mutex_semaphoreprova,1,0); /* release mutex */ LDST(&suspend->p_s); } else { /* wait */ insertBlocked(semkey,suspend); CAS(&mutex_semaphoreprova,1,0); /* release mutex */ scheduler(); } }
/** @brief The function will undertake one of the following actions: (1) If the offending process has NOT issued a SYS5, then invoke SYS2; (2) If the offending process has issued a SYS5, then pass up the exception. @return Void. */ HIDDEN void checkSYS5(int exceptionType, state_t *exceptionOldArea) { /* [Case 1] SYS5 has not been issued */ if (CurrentProcess->exceptionState[exceptionType] == 0) { /* Terminate the current process (SYS2) */ terminateProcess(); /* Call the scheduler */ scheduler(); } /* [Case 2] SYS5 has been issued */ else { /* Move current process Exception State Area into the processor Exception State Area */ saveCurrentState(exceptionOldArea, CurrentProcess->p_stateOldArea[exceptionType]); /* Load the processor state in order to start execution */ LDST(CurrentProcess->p_stateNewArea[exceptionType]); } }
/* * carica il processore con lo snapshot salvato nel TCB in testa * alla ready queue */ HIDDEN void upThread(void) { tcb_t *current; signed int time_snap; /* inizio del conteggio del tempo passato in codice kernel, solo per la prima * esecuzione, altrimenti inizializzazione prevista negli vari handler */ if (first_up) time_in_kernel = TOD_SNAPSHOT; current = removeThreadQ(&ready_queue); current_thread = current->tid; current->status = RUNN_THREAD; current = resolveTid(current_thread); if (current->cpu_remain == 0) current->cpu_remain = SCHED_TIME_SLICE; /* aggiorna il valore dello pseudo count evitando un possibile underflow */ if (pseudo_count < (last_time_slice + STCK(time_snap) - time_in_kernel)) /* STCK piu' preciso */ pseudo_count = 0; else pseudo_count -= last_time_slice + time_snap - time_in_kernel; /* settaggio interval timer considerando il tempo rimasto allo scadere dello pseudo clock*/ if (pseudo_count > SCHED_TIME_SLICE) { if (current->cpu_remain < SCHED_TIME_SLICE) { last_time_slice = TOD_SNAPSHOT; /* inizio intervallo di tempo del prossimo time slice */ SET_IT(current->cpu_remain); /* settaggio dell'interval timer */ } else { last_time_slice = TOD_SNAPSHOT; /* inizio intervallo di tempo del prossimo time slice */ SET_IT(SCHED_TIME_SLICE); /* settaggio dell'interval timer */ } } else { last_time_slice = TOD_SNAPSHOT; /* inizio intervallo di tempo del prossimo time slice */ SET_IT(pseudo_count); /* settaggio dell'interval timer */ } /* carica il processore con lo stato del thread */ LDST(&(current->cpu_snapshot)); /* esegue codice del thread appena caricato */ }
void sysBpHandler(){ int cause; int mode; //1-dovremmo salvare lo stato del registro //2-boh -> il tipo dice per evitare loop syscall :/ currentProcess->p_s.cpsr += //qualcosa; //3-prendiamo il mode mode= ((sysBp_old->cpsr & STATUS_SYS_MODE) >> 0x3); //forse funziona -> STATUS_SYS_MODE in uarmConst.h //4-cause interrupt cause=getCAUSE(); if(cause == EXC_SYSCALL){ //caso system call //controlla se è in user mode if(mode==TRUE){ //è definito da qualche parte il true? //controllo se è una delle 11 syscall if((sysBp_old->reg_a0 >= 1) && (sysBp_old->reg_a0 <= SYSCALL_MAX)){ //SYSCALL_MAX sta in const.h sysBp_old->CP15_Cause = setCAUSE(); //siamo sicuri non ci vadano parametri? //salva il sysbp old in pgmtrap old pgmTrapHandler(); } else{ //ERRORE!!! FACCIAMO UN ALTRA VOLTA!!! } } else{//caso kernel mode int ret; /* Salva i parametri delle SYSCALL */ U32 argv1 = sysBp_old->a2; U32 argv2 = sysBp_old->a3; U32 argv3 = sysBp_old->a4; /* Gestisce ogni singola SYSCALL */ switch(sysBp_old->a1) { case CREATEPROCESS: //currentProcess->p_state.reg_v0 = createProcess((state_t *) arg1); break; case TERMINATEPROCESS: //ris = terminateProcess((int) arg1); //if(currentProcess != NULL) currentProcess->p_state.reg_v0 = ris; break; case SEMOP: semaphoreOperation((int *) argv1, (int) argv2); break; case SPECSYSHDL: break; case SPECTLBHDL: break; case SPECPGMTHDL: break; case EXITTRAP: break; case GETCPUTIME: //currentProcess->p_state.reg_v0 = getCPUTime(); break; case WAITCLOCK: //waitClock(); break; case IODEVOP: break; case GETPID: currentProcess->p_state.reg_v0 = getPid(); break; /* case WAITIO: currentProcess->p_state.reg_v0 = waitIO((int) arg1, (int) arg2, (int) arg3); break; case GETPPID: currentProcess->p_state.reg_v0 = getPpid(); break; case SPECTLBVECT: specTLBvect((state_t *) arg1, (state_t *)arg2); break; case SPECPGMVECT: specPGMvect((state_t *) arg1, (state_t *)arg2); break; case SPECSYSVECT: specSYSvect((state_t *) arg1, (state_t *)arg2); break; */ default: /* Se non è già stata eseguita la SYS12, viene terminato il processo corrente */ if(currentProcess->ExStVec[ESV_SYSBP] == 0) { int ris; ris = terminateProcess(-1); if(currentProcess != NULL) currentProcess->p_state.reg_v0 = ris; } /* Altrimenti viene salvata la SysBP Old Area all'interno del processo corrente */ else { saveCurrentState(sysBp_old, currentProcess->sysbpState_old); LDST(currentProcess->sysbpState_new); } } scheduler(); } } else{ //caso breakpoint } }