Example #1
0
/**
@brief This function handles SYSCALL or Breakpoint exceptions, which occurs when a SYSCALL or BREAK assembler
instruction is executed.
@return Void.
*/
EXTERN void sysBpHandler()
{
	/* Save SYS/BP Old Area state */
	saveCurrentState(SYSBP_Old, &(CurrentProcess->p_s));

	/* Select handler accordingly to the exception type */
	switch (CAUSE_EXCCODE_GET(SYSBP_Old->CP15_Cause))
	{
		/* [Case 1] The exception is a system call */
		case EXC_SYSCALL:
			/* Distinguish between User Mode and Kernel Mode */
			((SYSBP_Old->cpsr & STATUS_SYS_MODE) == STATUS_USER_MODE)? syscallUserMode() : syscallKernelMode();
			break;

		/* [Case 2] The exception is a breakpoint */
		case EXC_BREAKPOINT:
			/* Distinguish whether SYS5 has been invoked or not */
			checkSYS5(SYSBK_EXCEPTION, SYSBP_Old);
			break;

		default: PANIC(); /* Anomaly */
	}
}
Example #2
0
/**********************************************************************
												 SYSBP_HANDLER

	Caricato all'arrivo di una eccezione di tipo SYSCALL/BREAKPOINT.
	Fornisce principalmente il servizio di message passing.
	In tutti i casi in cui è sollevata una eccezione diversa da SYSCALL
	di tipo 1 o 2 in Kernel Mode, questa routine, come le 
	altre due di questo modulo affidano il controllo del thread corrente
	ad un Trap Manager, se specificato, altrimenti viene terminato tutto
	il sottoalbero corrispondente.

**********************************************************************/
void sysbp_handler(){

	int exc_cause;
	int KUmode;	/* 0 se Kernel / 1 se User */

	tcb_t *trapped;
	tcb_t *manager;

	tcb_t *sender;
	tcb_t *receiver;

	U32 payload;
	U32 *reply;

	/* Aggiornamento tempo thread */
	current_thread->cpu_slice += (GET_TODLOW - current_thread_tod);
	current_thread->cpu_time += (GET_TODLOW - current_thread_tod);

	/*
		Salvo lo stato del processore del thread che ha sollevato l'eccezione, nel campo t_state del suo tcb.
		Lo stato è salvato nella old area dell'attuale eccezione.
		Modifico opportunamente il PC per non avere un ciclo nel ritorno dall'eccezione.
	*/
	save_state(sysbk_oldarea, &(current_thread->t_state));
	current_thread->t_state.pc_epc += WORD_SIZE;

	/* Recupero il tipo di eccezione avvenuta */
	exc_cause = CAUSE_EXCCODE_GET(sysbk_oldarea->cause);

	/* Controllo se Kernel o User Mode */
	KUmode = (sysbk_oldarea->status & STATUS_KUp) >> 3;
	
	/* Se l'eccezione è una SYSCALL 1 o 2 ed eseguita in kernel mode */
	if (KUmode == 0) {

		if (exc_cause == EXC_SYSCALL) {

			/* MsgSend */
			if (sysbk_oldarea->reg_a0 == SEND) {

				sender = current_thread;
				payload = sysbk_oldarea->reg_a2;
				/* Protezione SSI e incremento thread in attesa di servizio */
				if (sysbk_oldarea->reg_a1 == MAGIC_SSI) {
					receiver = SSI_tcb;
					soft_block_count++;
				}
				else 
					receiver = ((tcb_t *)(sysbk_oldarea->reg_a1));

				/* CASO TRAP MANAGER --> Intercettare messaggio TRAPTERMINATE / TRAPCONTINUE */
				if ((thereIs_manager(sender)) && (receiver->waiting_for == sender)) {

					/*** TRAPTERMINATE ***/
					if (payload == TRAPTERMINATE) {
						trapped = receiver;
						terminate(trapped);	/* Termino thread in wait_queue in attesa della decisione del Trap Manager */

						scheduler();
					}

					/*** TRAPCONTINUE ***/
					if (payload == TRAPCONTINUE) {
						trapped = receiver;
						insertThread(&ready_queue, outThread(&wait_queue, trapped)); /* Altrimenti lo risveglio */

						scheduler();
					}
				}

				/* Caso normale di MsgSend (vedi send) */
				sender->t_state.reg_v0 = send (sender, receiver, payload);

				scheduler();

			}

			/* MsgRecv */
			if (sysbk_oldarea->reg_a0 == RECV) {

				receiver = current_thread;
				reply = (U32 *)sysbk_oldarea->reg_a2;
				/* Protezione SSI (non decremento qui soft block count ma al momento di ricevimento servizio) */
				if (sysbk_oldarea->reg_a1 == MAGIC_SSI)
					sender = SSI_tcb;
				else 
					sender = ((tcb_t *)(sysbk_oldarea->reg_a1));


				/* MsgRecv (vedi recv) e restituisco sender direttamente (nel caso NON BLOCCANTE e non con SSIRequest) */
				current_thread->t_state.reg_v0 = (U32)recv(current_thread, ((tcb_t *)sysbk_oldarea->reg_a1), ((U32 *)sysbk_oldarea->reg_a2));
				
				scheduler();
			}

		}

	}

	
	/* TUTTI gli altri casi*/

	manager = current_thread->sysbp_manager_thread;

	/* Se il thread NON ha specificato un Trap Management thread per questa eccezione viene terminato */
	if (manager == NULL) {
		terminate(current_thread);
		current_thread = NULL;

		scheduler();
	}

	/* Se il thread HA invece specificato il gestore viene freezato */
	else {
		/* Invio messaggio al suo Trap manager con registro cause come payload */
		send(current_thread, manager, sysbk_oldarea->cause);

		/* Setto in TCB chi sto aspettando */
		current_thread->waiting_for = manager;

		/* Freeze del thread in attesa della decisione del manager */
		insertThread(&wait_queue, current_thread);

		current_thread = NULL;

		scheduler();
	}


}
Example #3
0
void sysBpHandler(){
	saveStateIn(sysbp_old, &currentProcess->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();
}