timer.c


/*************************************************************************
*                                                                        *
*   Processo gestore del tempo                                           *
*                                                                        *
*   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/supconst.h"

#include "../h/timer.h"

extern thr_t *SSI;

/* array per gestire l'allocazione delle richieste di ritardo */
HIDDEN timeq_t timeqTable[MAXTIMEQ];
HIDDEN timeq_t *tqfp;

/* lista ordinata per tempo delle richieste di ritardo */
HIDDEN timeq_t *req_queue = NULL;

/***
 * Processo servente di gestione del tempo. Esso mantiene una lista
 * di richieste di ritardo, e un contatore di tick di sistema (100msec).
 * Le richieste contengono il tempo nel futuro (espresso in tick)
 * in cui un client vuole essere avvisato (attraverso un messaggio).
 ***/ 
void
timer()
{
    register thr_t *sender;     /* R4 */
    register int *msg;          /* R3 */
    register timeq_t *p;
    long sys_tick = 0;
    int service = WAITCLOCK;

    /* inizializzazione dati del processo */
    initTimeQueue();

    /* manda la prima richiesta di WaitForClock */
    sender = SSI;
    msg = &service;
    DO_MSGSEND();
    DO_MSGRECV();
    /* la prima richiesta potrebbe essere inferiore a 100msec,
     * percio' bisogna farne una seconda prima di iniziare a servire
     * i ritardi
     */
    msg = &service;
    DO_MSGSEND();

    while(TRUE)
    {
        sender = ANYSENDER;
        DO_MSGRECV();

        if (sender == SSI)
        {   /* sono passati 100msec, prendi nota e rinnova la richiesta */
            sys_tick++;
            msg = &service;
            DO_MSGSEND();

            while ( (p = headQueue(req_queue)) != NULL && sys_tick > p->tq_alarm )
            {
                removeQueue(&req_queue);
                sender = p->tq_client;
                DO_MSGSEND();

                freeTimeQueue(p);
            }
        }
        else
        {
            if ( (p = allocTimeQueue()) == NULL )
            {
                HALT();
                /* panico!! */
            }
            else
            {
                p->tq_client = sender;
                p->tq_alarm = sys_tick + (long)msg * TICKPERSEC;
                insTimeReq(p);
            }
        } /* else */
    } /* while */
}

/* inserisce la richiesta mantenendo la lista ordinata in ordine
 * crescente per ritardo.
 * L'implementazione e` sempre tramite una lista circolare.
 */
void
insTimeReq(p)
register timeq_t *p;
{
    register timeq_t *tq;

    if (req_queue == NULL)
        req_queue = p->tq_next = p;
    else
    {
        tq = req_queue;

        while (p->tq_alarm > tq->tq_next->tq_alarm)
            tq = tq->tq_next;

        p->tq_next = tq->tq_next;
        tq->tq_next = p;
    }
}



[INDICE CODICE]