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