-
Notifications
You must be signed in to change notification settings - Fork 0
/
os3.c
148 lines (123 loc) · 3.02 KB
/
os3.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
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
146
147
148
// os3.c -- time slice between two user tasks and implement write syscall
#include <u.h>
enum { // processor fault codes
FMEM, // bad physical address
FTIMER, // timer interrupt
FKEYBD, // keyboard interrupt
FPRIV, // privileged instruction
FINST, // illegal instruction
FSYS, // software trap
FARITH, // arithmetic trap
FIPAGE, // page fault on opcode fetch
FWPAGE, // page fault on write
FRPAGE, // page fault on read
USER=16 // user mode exception
};
char task0_stack[1000];
char task0_kstack[1000];
char task1_stack[1000];
char task1_kstack[1000];
int *task0_sp;
int *task1_sp;
int current;
out(port, val) { asm(LL,8); asm(LBL,16); asm(BOUT); }
ivec(void *isr) { asm(LL,8); asm(IVEC); }
stmr(int val) { asm(LL,8); asm(TIME); }
halt(value) { asm(LL,8); asm(HALT); }
sys_write(fd, char *p, n) { int i; for (i=0; i<n; i++) out(fd, p[i]); return i; }
write() { asm(LL,8); asm(LBL,16); asm(LCL,24); asm(TRAP,S_write); }
task0()
{
while(current < 10)
write(1, "00", 2);
write(1,"task0 exit\n", 11);
halt(0);
}
task1()
{
while(current < 10)
write(1, "11", 2);
write(1,"task1 exit\n", 11);
halt(0);
}
swtch(int *old, int new) // switch stacks
{
asm(LEA, 0); // a = sp
asm(LBL, 8); // b = old
asm(SX, 0); // *b = a
asm(LL, 16); // a = new
asm(SSP); // sp = a
}
trap(int *sp, int c, int b, int a, int fc, unsigned *pc)
{
switch (fc) {
case FSYS + USER: // syscall
switch (pc[-1] >> 8) {
case S_write: a = sys_write(a, b, c); break;
default: sys_write(1, "panic! unknown syscall\n", 23); asm(HALT);
}
break;
case FTIMER: // timer
case FTIMER + USER:
out(1,'x');
if (++current & 1)
swtch(&task0_sp, task1_sp);
else
swtch(&task1_sp, task0_sp);
break;
case FKEYBD
case FKEYBD + USER:
sys_write(1, "keyboard\n", 25);asm(HALT);
break;
default:
default: sys_write(1, "panic! unknown interrupt\n", 25); asm(HALT);
}
}
alltraps()
{
asm(PSHA);
asm(PSHB);
asm(PSHC);
asm(LUSP); asm(PSHA);
trap(); // registers passed by reference/magic
asm(POPA); asm(SUSP);
asm(POPC);
asm(POPB);
asm(POPA);
asm(RTI);
}
trapret()
{
asm(POPA); asm(SUSP);
asm(POPC);
asm(POPB);
asm(POPA);
asm(RTI);
}
main()
{
int *kstack;
stmr(500000);
ivec(alltraps);
task0_sp = &task0_kstack[1000];
task0_sp -= 2; *task0_sp = &task0;
task0_sp -= 2; *task0_sp = USER; // fault code
task0_sp -= 2; *task0_sp = 0; // a
task0_sp -= 2; *task0_sp = 0; // b
task0_sp -= 2; *task0_sp = 0; // c
task0_sp -= 2; *task0_sp = &task0_stack[1000];
task0_sp -= 2; *task0_sp = &trapret;
task1_sp = &task1_kstack[1000];
task1_sp -= 2; *task1_sp = &task1;
task1_sp -= 2; *task1_sp = USER; // fault code
task1_sp -= 2; *task1_sp = 0; // a
task1_sp -= 2; *task1_sp = 0; // b
task1_sp -= 2; *task1_sp = 0; // c
task1_sp -= 2; *task1_sp = &task1_stack[1000];
task1_sp -= 2; *task1_sp = &trapret;
kstack = task0_sp;
asm(LL, 4); // a = kstack
asm(SSP); // sp = a
asm(LEV);
while(1);
}