sysservt.c


/*************************************************************************
*                                                                        *
*   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
}



[INDICE CODICE]