blob: 05f79891c1eef69b75a493a3eeebf7e0e924d0ea (
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include <isa.h>
#include <interp.h>
typedef struct Clock0link Clock0link;
typedef struct Clock0link {
void (*clock)(void);
Clock0link* link;
} Clock0link;
static Clock0link *clock0link;
static Lock clock0lock;
ulong clkrelinq;
void (*kproftick)(ulong); /* set by devkprof.c when active */
void (*archclocktick)(void); /* set by arch*.c when desired */
Timer*
addclock0link(void (*clock)(void), int)
{
Clock0link *lp;
if((lp = malloc(sizeof(Clock0link))) == 0){
print("addclock0link: too many links\n");
return nil;
}
ilock(&clock0lock);
lp->clock = clock;
lp->link = clock0link;
clock0link = lp;
iunlock(&clock0lock);
return nil;
}
void
delay(int l)
{
ulong i, j;
j = m->delayloop;
while(l-- > 0)
for(i=0; i < j; i++)
;
}
void
microdelay(int l)
{
ulong i;
l *= m->delayloop;
l /= 1000;
if(l <= 0)
l = 1;
for(i = 0; i < l; i++)
;
}
enum {
Timebase = 2, /* system clock cycles per time base cycle */
};
static ulong clkreload;
void
clockinit(void)
{
long x;
m->delayloop = m->cpuhz/1000; /* initial estimate */
do {
x = gettbl();
delay(10);
x = gettbl() - x;
} while(x < 0);
/*
* fix count
*/
m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase);
if(m->delayloop == 0)
m->delayloop = 1;
clkreload = (m->clockgen/Timebase)/HZ-1;
putdec(clkreload);
}
void
clockintr(Ureg *ur)
{
Clock0link *lp;
long v;
v = -getdec();
if(v > clkreload/2){
if(v > clkreload)
m->ticks += v/clkreload;
v = 0;
}
putdec(clkreload-v);
/* watchdog */
if(m->iomem->sypcr & (1<<2)){
m->iomem->swsr = 0x556c;
m->iomem->swsr = 0xaa39;
}
m->ticks++;
if(archclocktick != nil)
archclocktick();
if(up)
up->pc = ur->pc;
checkalarms();
if(m->machno == 0) {
if(kproftick != nil)
(*kproftick)(ur->pc);
if(canlock(&clock0lock)){
for(lp = clock0link; lp; lp = lp->link)
lp->clock();
unlock(&clock0lock);
}
}
if(up && up->state == Running){
if(cflag && up->type == Interp && tready(nil))
ur->cr |= 1; /* set flag in condition register for ../../libinterp/comp-power.c:/^schedcheck */
}
/* other preemption checks are done by trap.c */
}
uvlong
fastticks(uvlong *hz)
{
if(hz)
*hz = HZ;
return m->ticks;
}
|