|
|
Plan 9 NeXT
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "arp.h"
#include "../port/ipdat.h"
static Timer *timers; /* List of active timers */
static QLock tl; /* Protect timer list */
static Rendez Tcpack;
Rendez tcpflowr;
static void
deltimer(Timer *t)
{
if(timers == t)
timers = t->next;
if(t->next)
t->next->prev = t->prev;
if(t->prev)
t->prev->next = t->next;
}
/*
* Poke each tcp connection to recompute window size and
* acknowledgement timer
*/
void
tcpflow(void *x)
{
Ipifc *ifc;
Ipconv *cp, **p, **etab;
ifc = x;
etab = &ifc->conv[Nipconv];
for(;;) {
sleep(&tcpflowr, return0, 0);
for(p = ifc->conv; p < etab; p++) {
cp = *p;
if(cp == 0)
break;
if(cp->readq && cp->ref != 0 && !QFULL(cp->readq->next)) {
tcprcvwin(cp);
tcpacktimer(cp);
}
}
}
}
void
tcpackproc(void *junk)
{
Timer *t, *tp, *timeo;
USED(junk);
for(;;) {
timeo = 0;
qlock(&tl);
for(t = timers;t != 0; t = tp) {
tp = t->next;
if(t->state == TimerON) {
t->count--;
if(t->count == 0) {
deltimer(t);
t->state = TimerDONE;
t->next = timeo;
timeo = t;
}
}
}
qunlock(&tl);
for(;;) {
t = timeo;
if(t == 0)
break;
timeo = t->next;
if(t->state == TimerDONE)
if(t->func)
(*t->func)(t->arg);
}
tsleep(&Tcpack, return0, 0, MSPTICK);
}
}
void
tcpgo(Timer *t)
{
if(t == 0 || t->start == 0)
return;
qlock(&tl);
t->count = t->start;
if(t->state != TimerON) {
t->state = TimerON;
t->prev = 0;
t->next = timers;
if(t->next)
t->next->prev = t;
timers = t;
}
qunlock(&tl);
}
void
tcphalt(Timer *t)
{
if(t == 0)
return;
qlock(&tl);
if(t->state == TimerON)
deltimer(t);
t->state = TimerOFF;
qunlock(&tl);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.