-
Notifications
You must be signed in to change notification settings - Fork 0
/
ticker.c
119 lines (95 loc) · 1.98 KB
/
ticker.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
118
119
/*****************************************
Ticker
ticker.c Ticker facility
(C) 2015 Felix Palmen
https://github.com/Zirias
*****************************************/
#include <errno.h>
#include <time.h>
#include <dpmi.h>
#include "ticker.h"
static uclock_t nextTick;
static uclock_t tickTime;
static unsigned int ring;
enum wmethod {
WM_NONE,
WM_YIELD,
WM_IDLE,
WM_HLT
};
static enum wmethod method;
static int haveDosidle(void)
{
__dpmi_regs regs;
regs.x.ax = 0x1680;
__dpmi_int(0x28, ®s);
return regs.h.al ? 0 : 1;
}
static void dosidle(void)
{
__dpmi_regs regs;
/* the DOS Idle call is documented to return immediately if no other
* program is ready to run, therefore do one HLT if we can */
if (ring == 0)
__asm__ volatile("hlt");
regs.x.ax = 0x1680;
__dpmi_int(0x28, ®s);
if (regs.h.al) {
errno = ENOSYS;
}
}
void ticker_init(void)
{
/* determine protection ring */
__asm__("mov %%cs, %0\n\t"
"and $3, %0"
: "=r"(ring));
errno = 0;
__dpmi_yield();
if (errno) {
if (!haveDosidle()) {
if (ring) {
method = WM_NONE;
} else {
method = WM_HLT;
}
} else {
method = WM_IDLE;
}
} else {
method = WM_YIELD;
}
}
void ticker_done(void)
{
}
void ticker_start(int msec)
{
tickTime = msec * UCLOCKS_PER_SEC / 1000;
nextTick = uclock() + tickTime;
}
void ticker_stop()
{
}
void ticker_wait(void)
{
switch (method) {
case WM_NONE:
while (uclock() < nextTick)
;
break;
case WM_IDLE:
while (uclock() < nextTick)
dosidle();
break;
case WM_YIELD:
while (uclock() < nextTick)
__dpmi_yield();
break;
case WM_HLT:
while (uclock() < nextTick)
__asm__ volatile("hlt");
break;
}
nextTick += tickTime;
}