summaryrefslogtreecommitdiff
path: root/os/js/clock.c
blob: 581ee4417954907ac009fec799cc6841e4d55e3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"

#include	"ureg.h"

typedef struct Clock0link Clock0link;
typedef struct Clock0link {
	void		(*clock)(void);
	Clock0link*	link;
} Clock0link;

static Clock0link *clock0link;
static Lock clock0lock;

void
microdelay(int ms)
{
	int i;

	ms *= 13334;		/* experimentally indetermined */
	for(i=0; i<ms; i++)
		;
}

typedef struct Ctr Ctr;
struct Ctr
{
	ulong	lim;
	ulong	ctr;
	ulong	limnr;	/* non-resetting */
	ulong	ctl;
};
Ctr	*ctr;

void
clockinit(void)
{
	KMap *k;

	putphys(TIMECONFIG, 0);	/* it's a processor counter */
	k = kmappa(CLOCK, PTENOCACHE|PTEIO);
	ctr = (Ctr*)VA(k);
	ctr->lim = (CLOCKFREQ/HZ)<<10;
}

void
clock(Ureg *ur)
{
	Clock0link *lp;
	ulong i;

	USED(ur);

	i = ctr->lim;	/* clear interrupt */
	USED(i);
	 /* is this needed? page 6-43 801-3137-10 suggests so */
	ctr->lim = (CLOCKFREQ/HZ)<<10;

	m->ticks++;

	if(up)
		up->pc = ur->pc;

	checkalarms();

	lock(&clock0lock);
	for(lp = clock0link; lp; lp = lp->link)
		lp->clock();
	unlock(&clock0lock);

	if(up && up->state == Running) {
		if(anyready())
			sched();
	}
}

Timer*
addclock0link(void (*clockfunc)(void), int)
{
	Clock0link *lp;

	if((lp = malloc(sizeof(Clock0link))) == 0){
		print("addclock0link: too many links\n");
		return nil;
	}
	ilock(&clock0lock);
	lp->clock = clockfunc;
	lp->link = clock0link;
	clock0link = lp;
	iunlock(&clock0lock);
	return nil;
}

uvlong
fastticks(uvlong *hz)
{
	if(hz)
		*hz = HZ;
	return m->ticks;
}