/*************************************************************************
* *
* System Service Thread *
* *
* realizzato dal Gruppo 17 di Lab2 Anno Accademico 1995/96 *
* *
* Lorenzo Claudio Valerio Riccardo Emiliano *
* Coronati Lanconelli Paolini Solmi Trentini *
* *
**************************************************************************/
#include "../h/supconst.h"
#include "../h/tproc.h"
#include "../h/sst.h"
#include "../h/supglobals.e"
extern thr_t *timer_proc;
extern thr_t *disk_proc;
/* corpo del thread S.S.T. */
void
sysservt()
{
register thr_t *sender; /* R4 */
register servmsg_t *msg; /* R3 */
register int length; /* R2 */
#define R2 length
thr_t *client; /* thread che richiede il servizio */
tproc_t *tproc; /* T-process relativo al terminale */
int term_no; /* numero di terminale */
servmsg_t msg_buf;
term_no = R2;
tproc = tprocTable + term_no;
/*
* riceve l'indirizzo del padre (l'inizializzatore) e lo salva nella
* struttura T-process
*/
sender = ANYSENDER;
DO_MSGRECV();
/*
* crea i thread gestori e li assegna al processo
* inoltre crea (e lancia) il thread principale
*/
t_init(term_no, sender);
while (TRUE)
{
/* attende richiesta di servizio */
sender = ANYSENDER;
msg = &msg_buf.req;
length = sizeof(msg_buf);
/*
* facciamo la receive ALL per attendere richieste di servizio.
* Notare che il richiedente rimane bloccato sulla VSend, percio`
* a seconda che il servizio sia o no bloccante faremo la VReply
*/
VMSGRECV();
client = sender;
/* esegue il servizio richiesto */
switch (msg_buf.req.service)
{
case TERMREAD:
VMSGREPLY();
length = term_in(term_no, msg_buf.b_buf);
msg = &msg_buf.b_buf;
break;
case TERMWRITE:
VMSGREPLY();
length = term_out(term_no, msg_buf.req.str.string, length-1);
if (length > 0)
length = 0;
msg = msg_buf.req.str.string;
break;
case DELAY:
VMSGREPLY();
/* ridirige la richiesta al servente apposito */
sender = timer_proc;
msg = msg_buf.req.sec.no_secs;
DO_MSGSEND();
DO_MSGRECV();
length = 0;
break;
case TERMINATE:
do_terminate(term_no);
break;
case GETTID:
VMSGREPLY();
if (msg_buf.req.tno.tproc_no == -1)
msg_buf.i_buf[0] = tproc->T_mainthread;
else if (msg_buf.req.tno.tproc_no < MAXTPROC)
msg_buf.i_buf[0] = tprocTable[msg_buf.req.tno.tproc_no].T_mainthread;
else
msg_buf.i_buf[0] = NULL;
length = sizeof(msg_buf.i_buf[0]);
break;
#ifdef DISK_ON
case DISKGET:
{
struct {iores_t iores; char buffer[1]} *resp;
int fault = FALSE;
VMSGREPLY();
/* richiede il servizio */
sender = disk_proc;
msg_buf.i_buf[0] = IOREAD;
DO_MSGSEND();
/* attende l'esito del servizio */
DO_MSGRECV();
resp = msg;
length = -resp->iores.io_sta;
/* controlla che l'indirizzo passato sia valido */
if (msg_buf.req.dev.addr < BEGUSERADDR)
fault = TRUE;
else
/* copia il buffer */
MOVBCK(resp->buffer, msg_buf.req.dev.addr, SECTORSIZE);
/* comunica la fine della copia */
DO_MSGSEND();
if (fault)
killTerminal(term_no, "Segmentation violation");
break;
}
case DISKPUT:
{
int fault = FALSE;
VMSGREPLY();
/* richiede il servizio */
sender = disk_proc;
msg_buf.i_buf[0] = IOWRITE;
msg = msg_buf.i_buf;
DO_MSGSEND();
/* attende l'accettazione della richiesta */
DO_MSGRECV();
/* controlla che l'indirizzo passato sia valido */
if (msg_buf.req.dev.addr < BEGUSERADDR)
fault = TRUE;
else
/* copia il contenuto del settore nel disk buffer */
MOVBCK(msg_buf.req.dev.addr, msg, SECTORSIZE);
DO_MSGSEND();
/* attende l'esito del servizio */
DO_MSGRECV();
length = -msg->i_buf[0];
if (fault)
killTerminal(term_no, "Segmentation violation");
break;
}
#endif
default:
killTerminal(term_no, "Servizio richiesto sconosciuto");
break;
} /* switch */
sender = client;
VMSGSEND();
} /* while */
}
#undef R2
extern memmant();
extern progt();
extern syscallt();
#include "../h/bootcode.h"
/* Inizializza il T-processe */
HIDDEN void
t_init(term_no, parent)
int term_no;
thr_t *parent;
{
register thr_t *tproc;
register thr_t *thrid;
register int *begprivseg = BEGPRIVSEG;
state_t init_state;
tproc = tprocTable + term_no;
tproc->T_parent = parent;
tproc->T_process = tproc->T_sysservt->t_process;
/* initialize trap threads */
STST(&init_state);
init_state.s_r[2] = term_no;
/* Memory Management Trap Thread */
init_state.s_stl += SSTSTKSIZE;
init_state.s_sp = init_state.s_stl + MMTSTKSIZE;
init_state.s_pc = (int)memmant;
tproc->T_memmant = thrid = s_service(CREATHREAD, &init_state);
#ifdef SUP_DEBUG
if (thrid == NULL)
HALT();
#endif
s_service(SETMEMTRAP, thrid);
/* Program Trap Thread */
init_state.s_stl += MMTSTKSIZE;
init_state.s_sp = init_state.s_stl + PRGSTKSIZE;
init_state.s_pc = (int)progt;
tproc->T_progt = thrid = s_service(CREATHREAD, &init_state);
#ifdef SUP_DEBUG
if (thrid == NULL)
HALT();
#endif
s_service(SETPRGTRAP, thrid);
/* System Call Trap Thread */
init_state.s_stl += PRGSTKSIZE;
init_state.s_sp = init_state.s_stl + SCTSTKSIZE;
init_state.s_pc = (int)syscallt;
tproc->T_syscallt = thrid = s_service(CREATHREAD, &init_state);
#ifdef SUP_DEBUG
if (thrid == NULL)
HALT();
#endif
s_service(SETSYSTRAP, thrid);
/* move boot code into the beginning of private segment */
MOVBCK(bootcode, begprivseg, sizeof(bootcode));
begprivseg[1] = tproc->T_sysservt;
/* Main thread */
STST(&init_state);
init_state.s_sp = BEGSHARSEG;
init_state.s_stl = BEGSHARSEG - USRSTKSIZE;
init_state.s_pc = begprivseg;
init_state.s_ps1.ps_ku = FALSE;
init_state.s_sta = tproc->T_usrsegtable;
tproc->T_mainthread = s_service(CREATHREAD, &init_state);
#ifdef SUP_DEBUG
if (tproc->T_mainthread == NULL)
HALT();
#endif
}