trap.c


/*************************************************************************
*                                                                        *
*   Modulo per la gestione delle trap                                    *
*                                                                        *
*   realizzato dal Gruppo 17 di Lab2 Anno Accademico 1995/96             *
*                                                                        *
*   Lorenzo     Claudio       Valerio    Riccardo    Emiliano            *
*   Coronati    Lanconelli    Paolini    Solmi       Trentini            *
*                                                                        *
**************************************************************************/

/*
 * Alle routine di gestione viene passato in R4 l'indirizzo dell'area old
 * della relativa trap ed in R3 il tipo di trap
 */

#include "../h/types.h"
#include "../h/nucconst.h"

#include "../h/globals.e"
#include "../h/sendrecv.e"
#include "../h/scheduler.e"
#include "../h/ssi.e"

#ifdef  NUC_PROFILE
int sys_scount = 0;
int sys_rcount = 0;
int pass_count = 0;
#endif

/* gestore trap chiamate di sistema */
void
onSys()
{
    register state_t *sts;   /* R4 */
    register int trap_type; /* R3 */

    switch (sts->s_ps2.p2_sys.sys_no)
    {
    case MSGSEND:
        /*
         * Se la chiamata di sistema e' stata eseguita in modo kernel
         * viene eseguito il servizio, altrimenti viene simulata una
         * program trap per istruzione privilegiata
         */
        if (sts->s_ps1.ps_ku == 1)
        {
#ifdef  NUC_PROFILE
            sys_scount++;
#endif
            msgSend(run_thread, sts->s_r[4], sts->s_r[3]);
        }
        else
        {
            sts->s_ps2.p2_pr.pr_typ = PRIVINSTR;
            trap_type = PROGTRAP;
            passup();
        }
        break;
    case MSGRECV:
        if (sts->s_ps1.ps_ku == 1)
        {
#ifdef  NUC_PROFILE
            sys_rcount++;
#endif
            msgRecv();
        }
        else
        {
            sts->s_ps2.p2_pr.pr_typ = PRIVINSTR;
            trap_type = PROGTRAP;
            passup();
        }
        break;
    default:
        passup();
        break;
    }

    DISPATCH();
}

/* gestore trap programma e memory management */
/*
 * se il processo ha un tread di gestione della trap, gli manda un
 * messaggio e mette in attesa il thread che ha causato la trap,
 * altrimenti lo termina
 */
void
passup()
{
    register state_t *sts;   /* R4 */
    register int trap_type; /* R3 */
    register thr_t *trap_handler;

#ifdef  NUC_PROFILE
    pass_count++;
#endif

#ifdef  NUC_DEBUG
    /* determina se la trap e` avvenuta nel nucleo */
    if (nuc_stl == sts->s_stl)
    {
        if (trap_type == PROGTRAP)
        {
            switch (sts->s_ps2.p2_pr.pr_typ)
            {
            case ILOPCODE:
                panic("Illegal opcode program trap in nucleus");
                break;
            case NONSUPINSTR:
                panic("Non super.instr.program trap in nucleus");
                break;
            case PRIVINSTR:
                panic("Priv.instr.program trap in nucleus");
                break;
            case ILLINSTR:
                panic("Illegal instr.program trap in nucleus");
                break;
            case ODDADD:
                panic("Odd address program trap in nucleus");
                break;
            case NONPAGEAL:
                panic("Non page al.program trap in nucleus");
                break;
            case NONEXISTMEM:
                panic("Non existent mem.program trap in nucleus");
                break;
            case STKLIMYELLOW:
                panic("stack limit yello program trap in nucleus");
                break;
            case STKLIMRED:
                panic("stack limit red program trap in nucleus");
                break;
            case ZERODIV:
                panic("zero div.program trap in nucleus");
                break;
            default:
                panic("Unknown program trap in nucleus");
                break;
            }
        }
        else if (trap_type == SYSTRAP)
            panic("System trap in nucleus");
        else
            panic("Memory Management trap in nucleus");
    }
#endif

    /* verifica l'esistenza del thread gestore */
    trap_handler = (&run_proc->p_prgtrap)[trap_type];
    if (trap_handler == NULL)
    {
        termProc(run_thread);
        run_proc = NULL;
    }
    else
    {
        SAVESTATE();
        run_thread->t_handler = trap_handler;
        msgSend(run_thread, trap_handler, &run_thread->t_s);
        sleepProc(ANYTRAP);
    }
    schedule();
    NEWSTATE();

    LOADTIMER();
    DISPATCH();
}


[INDICE CODICE]