/*************************************************************************
* *
* Modulo di gestione dei messaggi *
* *
* realizzato dal Gruppo 17 di Lab2 Anno Accademico 1995/96 *
* *
* Lorenzo Claudio Valerio Riccardo Emiliano *
* Coronati Lanconelli Paolini Solmi Trentini *
* *
**************************************************************************/
#include "../h/types.h"
#include "../h/nucconst.h"
#include "../h/globals.e"
#include "../h/scheduler.e"
#include "../h/msgqueue.e"
void
msgSend(from, to, message)
thr_t *from, *to;
int message;
{
register state_t *sts; /* R4 */
register msg_t *msg;
register thr_t *dest = to;
#ifdef NUC_DEBUG
if (from == NULL || dest == NULL || !EVEN(dest) || dest < BEGINKERNEL)
panic("msgSend(): bad parameters");
#endif
/* controllo che il destinatario sia valido */
if (dest->t_process != NULL)
{
/* il destinatario e' in attesa di un nostro messaggio */
if (dest->t_waitfrom == from)
{
dest->t_s.s_r[4] = from;
dest->t_s.s_r[3] = message;
if (from != SSI)
outWaitThread(&from->t_replyqueue, dest);
wakeupProc(dest);
}
else if (dest->t_waitfrom == ANYSENDER)
{
dest->t_s.s_r[4] = from;
dest->t_s.s_r[3] = message;
wakeupProc(dest);
}
/*
* il destinatario attende che il gestore di trap finisca il
* proprio lavoro
*/
else if (dest->t_waitfrom == ANYTRAP && dest->t_handler == from)
{
wakeupProc(dest);
}
/*
* il destinatario non e' in attesa ed il messaggio viene
* messo in coda
*/
else if ((msg = allocMessage()) != NULL)
{
msg->m_sender = from;
msg->m_message = message;
insertMessage(&dest->t_msgqueue, msg);
}
else
panic("No more messages");
}
/* caso in cui il destinatario sia stato terminato */
else
{
#ifdef NUC_DEBUG
error("Message sent to died thread");
#endif
/*
* controlla che il mittente non sia proprio il gestore delle
* program trap
*/
if (from == from->t_process->p_prgtrap)
from->t_process->p_prgtrap = NULL;
sts->s_ps2.p2_pr.pr_typ = SENDTODEADTHR;
msg = PROGTRAP;
passup();
}
}
void
msgRecv()
{
register state_t *sts; /* R4 ** passato dalla OnSys() */
register msg_t *msg;
register thr_t *from = sts->s_r[4];
/* controlla se il messaggio che attendiamo e' arrivato */
msg = (from == ANYSENDER) ?
removeMessage(&run_thread->t_msgqueue) :
keyMessage(&run_thread->t_msgqueue, from);
/*
* se il messaggio che attende non e' gia' arrivato, si mette in
* attesa
*/
if (msg == NULL)
{
if (from == ANYSENDER || from == ANYTRAP)
{
SAVESTATE();
sleepProc(from);
schedule();
NEWSTATE();
LOADTIMER();
DISPATCH();
}
/* controlla che il thread da cui attendiamo non sia morto */
else if (from->t_process != NULL)
{
SAVESTATE();
if (from != SSI)
insWaitThread(&from->t_replyqueue, run_thread);
sleepProc(from);
schedule();
NEWSTATE();
LOADTIMER();
DISPATCH();
}
else
{
#ifdef NUC_DEBUG
error("Waiting from dead thread");
#endif
sts->s_ps2.p2_pr.pr_typ = RECVFROMDEADTHR;
msg = PROGTRAP;
passup();
}
}
else
{
sts->s_r[3] = msg->m_message;
sts->s_r[4] = msg->m_sender;
freeMessage(msg);
}
}