Rev 1 | Rev 3 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | ha | 1 | label next_usage_update dword at 0xB008 |
2 | label timer_ticks dword at 0xFDF0 |
||
3 | |||
4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
5 | ;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
||
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
7 | |||
8 | align 32 |
||
9 | irq0: |
||
10 | |||
11 | cmp [error_interrupt],-1 |
||
12 | je no_error_in_previous_process |
||
13 | |||
14 | mov edi,[error_interrupt] |
||
15 | shl edi, 3 |
||
16 | mov [edi+tss0i_l +5], word 01010000b *256 +11101001b |
||
17 | |||
18 | mov edi,[error_interrupt] |
||
19 | shl edi,7 |
||
20 | add edi,0x290000 |
||
21 | mov esi,[error_interrupt_entry] |
||
22 | mov [edi+l.eip-tss_sceleton],esi |
||
23 | mov [edi+l.eflags-tss_sceleton],dword 0x11002 |
||
24 | |||
25 | mov [0xffff],byte 0 |
||
26 | |||
27 | mov [error_interrupt],-1 |
||
28 | |||
29 | no_error_in_previous_process: |
||
30 | |||
31 | mov edi,[0x3000] |
||
32 | shl edi, 3 |
||
33 | ; fields of TSS descriptor: |
||
34 | mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
||
35 | |||
36 | inc dword [timer_ticks] |
||
37 | |||
38 | mov eax, [timer_ticks] |
||
39 | ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||
40 | call playNote ; <<<--- INSERT THIS LINE !!!!!!!!!! |
||
41 | ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||
42 | |||
43 | cmp eax,[next_usage_update] |
||
44 | jb .nocounter |
||
45 | add eax,100 |
||
46 | mov [next_usage_update],eax |
||
47 | call updatecputimes |
||
48 | .nocounter: |
||
49 | |||
50 | mov edi, [0x3010] |
||
51 | |||
52 | mov ebx, [edi+0x18] ; time stamp counter add |
||
53 | call _rdtsc |
||
54 | sub eax, ebx |
||
55 | add eax, [edi+0x14] ; counter sum |
||
56 | mov [edi+0x14], eax |
||
57 | |||
58 | mov ebx,[0x3000] |
||
59 | |||
60 | cmp [0xffff], byte 1 ;1 |
||
61 | je do_not_change_task ;je |
||
62 | |||
63 | .waiting_for_termination: |
||
64 | .waiting_for_reuse: |
||
65 | .waiting_on_queue: |
||
66 | add edi,0x20 |
||
67 | inc ebx |
||
68 | |||
69 | mov al, byte [edi+0xA] |
||
70 | cmp al, 3 |
||
71 | je .waiting_for_termination |
||
72 | cmp al, 4 |
||
73 | je .waiting_for_termination |
||
74 | cmp al, 9 |
||
75 | je .waiting_for_reuse |
||
76 | cmp al, 16 |
||
77 | je .waiting_on_queue |
||
78 | cmp al, 17 |
||
79 | je .waiting_on_queue |
||
80 | |||
81 | cmp ebx,[0x3004] |
||
82 | jbe nsched0 |
||
83 | mov ebx,1 |
||
84 | mov edi,0x3020 |
||
85 | |||
86 | nsched0: |
||
87 | |||
88 | mov [0x3000],ebx |
||
89 | mov [0x3010],edi |
||
90 | |||
91 | do_not_change_task: |
||
92 | |||
93 | mov edx,[0x3000] |
||
94 | lea edx,[tss0sys+8*edx] |
||
95 | ;mov [8*0x40+idts+8+0], word 0 |
||
96 | mov [8*0x40+idts+8+2],dx |
||
97 | ;mov [8*0x40+idts+8+4],word 11100101b*256 |
||
98 | ;mov [8*0x40+idts+8+6], word 0 |
||
99 | |||
100 | call _rdtsc |
||
101 | mov [edi+0x18],eax |
||
102 | |||
103 | cmp [0xffff],byte 0 |
||
104 | je nodecffff |
||
105 | dec byte [0xffff] |
||
106 | nodecffff: |
||
107 | |||
108 | |||
109 | shl ebx, 3 |
||
110 | xor eax, eax |
||
111 | add ebx, tss0 |
||
112 | mov word [0xB004], bx ; selector ;mov [tss_s],bx |
||
113 | mov dword [0xB000], eax ; offset |
||
114 | |||
115 | mov al,0x20 ; send End Of Interrupt signal |
||
116 | mov dx,0x20 |
||
117 | out dx,al |
||
118 | .switch: |
||
119 | jmp pword [0xB000] |
||
120 | inc [context_counter] ;noname & halyavin |
||
121 | jmp irq0 |
||
122 | |||
123 | iglobal |
||
124 | context_counter dd 0 ;noname & halyavin |
||
125 | endg |
||
126 | |||
127 | |||
128 | align 4 |
||
129 | change_task: |
||
130 | |||
131 | mov [0xffff],byte 2 |
||
132 | |||
133 | dec dword [timer_ticks] ; because irq0 will increase it |
||
134 | |||
135 | int 0x20 ; irq0 handler |
||
136 | |||
137 | ret |
||
138 | |||
139 | |||
140 | |||
141 | align 4 |
||
142 | updatecputimes: |
||
143 | |||
144 | mov eax,[idleuse] |
||
145 | mov [idleusesec],eax |
||
146 | mov [idleuse],dword 0 |
||
147 | mov ecx, [0x3004] |
||
148 | mov edi, 0x3020 |
||
149 | .newupdate: |
||
150 | mov ebx,[edi+0x14] |
||
151 | mov [edi+0x1c],ebx |
||
152 | mov [edi+0x14],dword 0 |
||
153 | add edi,0x20 |
||
154 | dec ecx |
||
155 | jnz .newupdate |
||
156 | |||
157 | ret |
||
158 | |||
159 | |||
160 | |||
161 | ; |
||
162 | ; Wait queue is 16 bytes |
||
163 | ; dd return code +12 |
||
164 | ; dd pointer to process +8 |
||
165 | ; dd prev +4 |
||
166 | ; dd next +0 |
||
167 | ; |
||
168 | ; eax - pointer to pointer to the wait queue |
||
169 | ; return: |
||
170 | ; ecx - return code |
||
171 | sleep_on_queue: |
||
172 | sub esp,16 ; reserve space for wait node |
||
173 | mov ecx,esp ; ecx=this_node, [eax]=queue |
||
174 | |||
175 | pusha |
||
176 | |||
177 | mov ebx,[0x3010] ; get pointer to the current process |
||
178 | mov [ecx+8],ebx |
||
179 | |||
180 | pushf |
||
181 | cli ; adding element to the wait queue must be atomic |
||
182 | |||
183 | mov edi,[eax] ; edi=queue |
||
184 | and edi,edi ; check if queue is empty |
||
185 | jz .is_empty |
||
186 | |||
187 | ; add element at the end of wait queue |
||
188 | |||
189 | mov edx,[edi+4] ; get pointer to prev edx=queue->prev |
||
190 | mov [ecx+4],edx ; this_node->prev=queue->prev |
||
191 | mov [ecx+0],edi ; this_node->next=queue |
||
192 | mov [edx+0],ecx ; this_node->prev->next=this_node |
||
193 | mov [edi+4],ecx ; queue->prev=this_node |
||
194 | jmp .added_ok |
||
195 | .is_empty: |
||
196 | ; set this element as first in the queue |
||
197 | mov [ecx+0],ecx ; this_node->next=this_node |
||
198 | mov [ecx+4],ecx ; this_node->prev=this_node |
||
199 | mov [eax],ecx ; [queue]=this_node |
||
200 | .added_ok: |
||
201 | |||
202 | popf ; we can safely restore interrupts |
||
203 | |||
204 | mov [ebx+0xa],byte 17 ; set current task state as sleeping |
||
205 | call change_task ; schedule new thread |
||
206 | |||
207 | ; someone has called wake_up_queue |
||
208 | |||
209 | pushf ; disable interrupts |
||
210 | cli |
||
211 | |||
212 | mov edx,[ecx+0] ; edx=this_node->next |
||
213 | mov esi,[ecx+4] ; esi=this_node->prev |
||
214 | |||
215 | ; check if we need to remove this node from head |
||
216 | cmp [eax],ecx |
||
217 | jne .no_head |
||
218 | |||
219 | cmp [ecx+0],ecx ; check if queue is empty |
||
220 | jne .not_empty |
||
221 | |||
222 | mov [eax],dword 0 |
||
223 | jmp .no_head |
||
224 | |||
225 | .not_empty: |
||
226 | mov [eax],edx |
||
227 | |||
228 | ; remove our node from the queue (this must be atomic) |
||
229 | .no_head: |
||
230 | mov [edx+4],esi ; this_node->next->prev=this_node->prev |
||
231 | mov [esi+0],edx ; this_node->prev->next=this_node->next |
||
232 | |||
233 | popf |
||
234 | popa |
||
235 | add esp,12 |
||
236 | pop ecx |
||
237 | ret |
||
238 | |||
239 | ; eax - pointer to the wait queue |
||
240 | ; ebx - wake up all (1=yes, 0=no) |
||
241 | ; ecx - return code |
||
242 | ; return: |
||
243 | ; ebx - number of processes woken |
||
244 | wake_up_queue: |
||
245 | and eax,eax |
||
246 | jnz .nz |
||
247 | ret |
||
248 | .nz: |
||
249 | push eax |
||
250 | push ebx |
||
251 | push ecx |
||
252 | push edx |
||
253 | push esi |
||
254 | |||
255 | pushf |
||
256 | cli |
||
257 | |||
258 | xor ebx,ebx |
||
259 | mov edx,eax |
||
260 | .wake_loop: |
||
261 | |||
262 | mov [edx+12],ecx |
||
263 | mov esi,[edx+8] |
||
264 | mov byte [esi+0xa],0 |
||
265 | inc ebx |
||
266 | |||
267 | mov edx,[edx+0] |
||
268 | cmp edx,eax |
||
269 | jne .wake_loop |
||
270 | |||
271 | and ebx,ebx |
||
272 | jz .wake_up_1 |
||
273 | |||
274 | .return_it: |
||
275 | popf |
||
276 | pop esi |
||
277 | pop edx |
||
278 | pop ecx |
||
279 | add esp,4 |
||
280 | pop eax |
||
281 | ret |
||
282 | .wake_up_1: |
||
283 | mov [eax+12],ecx |
||
284 | mov ecx,[eax+8] |
||
285 | mov byte [ecx+0xa],0 |
||
286 | jmp .return_it---><---><<---> |