-
Notifications
You must be signed in to change notification settings - Fork 0
/
timer.c
118 lines (92 loc) · 2.34 KB
/
timer.c
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
#include "bootpack.h"
#define PIT_CTRL 0x0043
#define PIT_CNT0 0x0040
#define TIMER_FLAGS_ALLOC 1
#define TIMER_FLAGS_USED 2
#define MAX_TIMEOUT 0xffffffff
TimerControl timerctl;
extern Timer *task_timer;
void init_pit() {
int interval = 11932;
io_out8(PIT_CTRL, 0x34);
io_out8(PIT_CNT0, interval & 0x00ff);
io_out8(PIT_CNT0, (interval & 0xff00) >> 8);
timerctl.count = 0;
timerctl.next_timeout = MAX_TIMEOUT;
for (int i = 0; i < MAX_TIMERS; i++) {
timerctl.timers0[i].flags = 0;
}
// 番兵
Timer *stop = timer_alloc();
stop->timeout = MAX_TIMEOUT;
stop->flags = TIMER_FLAGS_USED;
stop->next = NULL;
timerctl.timer_head = stop;
}
Timer *timer_alloc() {
for (int i = 0; i < MAX_TIMERS; i++) {
if (timerctl.timers0[i].flags == 0) {
timerctl.timers0[i].flags = TIMER_FLAGS_ALLOC;
return &timerctl.timers0[i];
}
}
return NULL;
}
void timer_init(Timer *timer, FIFO32 *fifo, byte data) {
timer->fifo = fifo;
timer->data = data;
timer->next = NULL;
}
void timer_free(Timer *timer) {
timer->flags = 0;
}
void timer_settime(Timer *timer, unsigned timeout) {
timer->timeout = timeout + timerctl.count;
timer->flags = TIMER_FLAGS_USED;
int eflags = io_load_eflags();
io_cli();
Timer *current = timerctl.timer_head, *prev = NULL;
while (current) {
if (current->timeout >= timer->timeout) {
break;
}
prev = current;
current = current->next;
}
if (prev) {
prev->next = timer;
timer->next = current;
} else {
Timer *head = timerctl.timer_head;
timerctl.timer_head = timer;
timer->next = head;
}
timerctl.next_timeout = timerctl.timer_head->timeout;
io_store_eflags(eflags);
}
void inthandler20(int *esp) {
io_out8(PIC0_OCW2, 0x60);
timerctl.count++;
if (timerctl.next_timeout > timerctl.count) {
return;
}
bool task_switch_flag = false;
Timer *current = timerctl.timer_head;
for (; current ; current = current->next) {
if (current->timeout > timerctl.count) {
break;
}
// タイムアウト
current->flags = TIMER_FLAGS_ALLOC;
if (current == task_timer) {
task_switch_flag = true;
} else {
fifo32_push(current->fifo, current->data);
}
}
timerctl.timer_head = current;
timerctl.next_timeout = timerctl.timer_head->timeout;
if (task_switch_flag) {
task_switch();
}
}