-
Notifications
You must be signed in to change notification settings - Fork 2
/
proc_manager.s
184 lines (151 loc) · 3.72 KB
/
proc_manager.s
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# Steve Johnson
# proc_manager.s handles loading and executing programs
# load_process is probably the most interesting thing in here.
#include proc_storage.s
.text
new_pid:
{
# Summary:
# Loads last PID generated, makes a new one, saves the result
@khcb_addr = $s0
@next_pid = $s1
@err = $s2
@pid = $s3
khcb_getaddr @khcb_addr
get $zero $zero @khcb_addr @next_pid @err
bnez @err newpid_err
addu @pid @next_pid $0
addu @next_pid @next_pid 0x1
put $zero $zero @khcb_addr @next_pid @err
addu $v0 @pid $zero
bnez @err newpid_err
return
newpid_err:
println errmsg
li $v0 10
syscall
.data
errmsg: .asciiz "error in new_pid"
.text
}
.text
get_cmgr_head:
{
# Summary:
# Loads the address of the head of the context manager linked list
@khcb_addr = $s0
@h = $s1
@err = $s2
khcb_getaddr @khcb_addr
geti 1 $zero @khcb_addr @h @err
bnez @err ch_err
addu $v0 @h $zero
return
ch_err:
println errmsg
li $v0 10
syscall
.data
errmsg: .asciiz "error in get_cmgr_head"
.text
}
.text
#init_context_manager()
init_context_manager:
{
@pid = $s0
@h = $s1
@err = $s2
@pcb_id = $s3
@khcb_addr = $s4
#Initialize a PCB on the kernel heap
khcb_getaddr @khcb_addr
alloci 50 @khcb_addr @pcb_id
khcb_writeback @khcb_addr
#Get a new PID
call new_pid
addu @pid $v0 $zero
#Initialize the linked list with the new values
addu $a0 @pid $zero
addu $a1 @pcb_id $zero
call ll_init
addu @h $v0 $zero
#Put the list head and current PID into kernel static space
puti 1 $zero @khcb_addr @h @err
bnez @err lfp_err
puti 2 $zero @khcb_addr @pid @err
bnez @err lfp_err
#Store PCB and PID in other static data areas
#to initialize parts of the interrupt handler
la $t0 current_pcb
sw @pcb_id 0($t0)
la $t0 current_pid
sw @pid 0($t0)
return
lfp_err:
println error_msg
li $v0 10
syscall
.data
default_data_amt: .word 0x00004000
error_msg: .asciiz "init_context_manager failed"
.text
}
#load_process(program_counter)
load_process:
{
@pid = $s0
@h = $s1
@err = $s2
@pcb_id = $s3
@khcb_addr = $s4
@pc = $s5
@sp = $s6
@stack_id = $s7
addu @pc $a0 $zero
#Initialize a PCB on the kernel heap
khcb_getaddr @khcb_addr
alloci 50 @khcb_addr @pcb_id
khcb_writeback @khcb_addr
#Get the list head
call get_cmgr_head
addu @h $v0 $zero
#And a new PID
call new_pid
addu @pid $v0 $zero
#Append the new data to the context manager linked list
addu $a0 @h $zero
addu $a1 @pid $zero
addu $a2 @pcb_id $zero
call ll_append
#Initialize the program counter and print a status message
subu @pc @pc 4
mtc0 @pc $14
println_hex pc_msg @pc
#Save the procedure so it will be loaded normally by the interrupt handler
addu $a0 @pcb_id $zero
li $a1 0
call save_proc
{
#Put some sane values in stack storage
khcb_getaddr @khcb_addr
geti 4 $zero @khcb_addr @sp @err
addu $a0 @sp $zero
call save_stack
addu @stack_id $v0 $zero
puti 4 @pcb_id @khcb_addr @stack_id @err
puti 7 @pcb_id @khcb_addr @sp @err
}
#addu $a0 @h $zero
#call ll_print
return
lfp_err:
println error_msg
li $v0 10
syscall
.data
default_data_amt: .word 0x00004000
error_msg: .asciiz "load_process failed"
pc_msg: .asciiz "Spawning new process at PC = "
.text
}