Esempio n. 1
0
/**********************************************************************
														TERMINATE

	Si occupa di:
	-Uccidere root e tutti i figli ricorsivamente
	-Rimettere i thread nella lista dei liberi
	-Togliere i thread dalle varie liste/array in cui sono presenti
	-Decrementare il valore di thread_count
	-Pulire la inbox da eventuali messaggi

**********************************************************************/
void terminate (tcb_t *target) {
	
	msg_t *msg;
	tcb_t *child;

	/* Se ha un padre lo elimino dai suoi figli */
	outChild(target);

	/* Caso ricorsivo -> HA figli (su cui viene chiamata la terminate) */
	while (TRUE) {
		if ( (child = removeChild(target)) == NULL ) break; /* Passa al caso base e pulisce thread, liste, messaggi... */
		terminate(child);
	}

	/* Caso base -> NON ha figli */

	/* Se è in qualche lista o è il thread corrente lo elimino */
	if (((outThread(&ready_queue, target)) != NULL) || (current_thread == target)) {

		/* Pulisco la inbox */
		while (TRUE) {
			if ( (msg = popMessage(&(target->t_inbox), NULL)) == NULL ) break;
			freeMsg(msg);
		}

		/* Se è un manager lo elimino dal trap_managers array */
		delete_manager(target);

		if (current_thread == target) current_thread=NULL;

		/* Restituisco ai thread liberi */
		freeTcb(target);
		thread_count--;
	}

	else if (outThread(&wait_queue, target)) {

		/* Decremento contatore processi in attesa I/O o SSI */	
		if (target->waiting_for == SSI_tcb)
			soft_block_count--;

		/* Tutto come caso precedente*/
		while (TRUE) {
			if ( (msg = popMessage(&(target->t_inbox), NULL)) == NULL ) break;
			freeMsg(msg);
		}

		delete_manager(target);
		freeTcb(target);
		thread_count--;
	}

	else PANIC();
}
Esempio n. 2
0
/**********************************************************************
														SEND

	Invia un messaggio come richiesto dal sender al destinatario
	specificato nel registro a1 (receiver), col payload specificato
	al registro	a2 (payload).
	Operazione NON BLOCCANTE.

**********************************************************************/
int send (tcb_t *sender, tcb_t *target, U32 payload){

	msg_t *msg;
	tcb_t *_sender_;

	/* Protezione SSI */
	if (sender == SSI_tcb)
		_sender_ = (tcb_t *)MAGIC_SSI;
	else 
		_sender_ = sender;

	/* Destinatario in ready_queue o thread corrente */
	if ( ((thereIsThread(&ready_queue, target)) != NULL ) || (current_thread == target) ) {
		if ((msg = allocMsg()) == NULL) PANIC();
		/* Creazione e compilazione messaggio */

		msg->m_sender = _sender_;
		msg->m_message = payload;

		/* Priorità allo Pseudo Clock Tick -> Messaggio in testa */
		if (_sender_ == (tcb_t*)BUS_INTERVALTIMER)
			pushMessage(&(target->t_inbox), msg);
		/* Trattamento normale -> Messaggio in coda */
		else insertMessage(&(target->t_inbox), msg);

		return (MSGGOOD);
	}
	
	/* Destinatario in wait_queue */
	else if ((thereIsThread(&wait_queue, target)) != NULL ) {

		/* 
				Se sta aspettando un messaggio da questo thread 
				o da chiunque sveglio il thread dest togliendolo 
				dalla wait_queue e lo inserisco nella ready_queue
				passandogli il payload dove mi aveva richiesto e 
				che avevo salvato nel TCB nel	campo "reply".
		*/
		if ((target->waiting_for == _sender_) || (target->waiting_for == ANYMESSAGE)) {
			*(target->reply) = payload;

			/* Risveglio il thread */
			insertThread(&ready_queue, outThread(&wait_queue, target));

			/* Risettaggio campi per message passing */
			target->waiting_for = (tcb_t *)-1;
			target->reply = (U32 *)-1;

			/* Decremento soft block count se caso SSI e restituisco sender al destinatario */
			if (_sender_ == SSI_tcb)
				soft_block_count--;

			target->t_state.reg_v0 = (U32)_sender_;
			
			return (MSGGOOD);
		}

		/* Destinatario momentaneamente in attesa di un altro mittente */
		else {
			/* Tutto come sopra */
			if ((msg = allocMsg()) == NULL) PANIC();

			msg->m_sender = _sender_;
			msg->m_message = payload;

			if (sender == (tcb_t *)BUS_INTERVALTIMER)
				pushMessage(&(target->t_inbox), msg);

			else insertMessage(&(target->t_inbox), msg);

			return (MSGGOOD);
		}

	}

	/* Nessuno dei casi precedenti --> potrebbe essere stato terminato il thread */
	return (MSGNOGOOD);
	
}
Esempio n. 3
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();
	}


}
Esempio n. 4
0
void ProduceDoc::recupSlot(const QString & text){
    emit outThread(text);
}