Rev 3617 | Rev 5130 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3617 | Rev 4700 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; |
4 | ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
4 | ;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; |
5 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; Distributed under terms of the GNU General Public License ;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7 | 7 | ||
8 | $Revision: 3617 $ |
8 | $Revision: 4700 $ |
9 | 9 | ||
10 | 10 | ||
11 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
11 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
12 | ;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
12 | ;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
14 | 14 | ||
15 | 15 | ||
16 | align 32 |
16 | align 32 |
17 | irq0: |
17 | irq0: |
18 | pushad |
18 | pushad |
19 | Mov ds, ax, app_data |
19 | Mov ds, ax, app_data |
20 | mov es, ax |
20 | mov es, ax |
21 | inc [timer_ticks] |
21 | inc [timer_ticks] |
22 | mov eax, [timer_ticks] |
22 | mov eax, [timer_ticks] |
23 | call playNote ; <<<--- Speaker driver |
23 | call playNote ; <<<--- Speaker driver |
24 | sub eax, [next_usage_update] |
24 | sub eax, [next_usage_update] |
25 | cmp eax, 100 |
25 | cmp eax, 100 |
26 | jb .nocounter |
26 | jb .nocounter |
27 | add [next_usage_update], 100 |
27 | add [next_usage_update], 100 |
28 | call updatecputimes |
28 | call updatecputimes |
29 | .nocounter: |
29 | .nocounter: |
30 | xor ecx, ecx ; send End Of Interrupt signal |
30 | xor ecx, ecx ; send End Of Interrupt signal |
31 | call irq_eoi |
31 | call irq_eoi |
32 | ; btr dword[DONT_SWITCH], 0 |
- | |
33 | ; jc .return |
- | |
- | 32 | ||
34 | mov bl, SCHEDULE_ANY_PRIORITY |
33 | mov bl, SCHEDULE_ANY_PRIORITY |
35 | call find_next_task |
34 | call find_next_task |
36 | jz .return ; if there is only one running process |
35 | jz .return ; if there is only one running process |
37 | call do_change_task |
36 | call do_change_task |
38 | .return: |
37 | .return: |
39 | popad |
38 | popad |
40 | iretd |
39 | iretd |
41 | 40 | ||
42 | align 4 |
41 | align 4 |
43 | change_task: |
42 | change_task: |
44 | pushfd |
43 | pushfd |
45 | cli |
44 | cli |
46 | pushad |
45 | pushad |
47 | if 0 |
- | |
48 | ; \begin{Mario79} ; <- must be refractoried, if used... |
- | |
49 | cmp [dma_task_switched], 1 |
- | |
50 | jne .find_next_task |
- | |
51 | mov [dma_task_switched], 0 |
- | |
52 | mov ebx, [dma_process] |
- | |
53 | cmp [CURRENT_TASK], ebx |
- | |
54 | je .return |
- | |
55 | mov edi, [dma_slot_ptr] |
- | |
56 | mov [CURRENT_TASK], ebx |
- | |
57 | mov [TASK_BASE], edi |
- | |
58 | jmp @f |
- | |
59 | .find_next_task: |
- | |
60 | ; \end{Mario79} |
- | |
61 | end if |
- | |
62 | mov bl, SCHEDULE_ANY_PRIORITY |
46 | mov bl, SCHEDULE_ANY_PRIORITY |
63 | call find_next_task |
47 | call find_next_task |
64 | jz .return ; the same task -> skip switch |
48 | jz .return ; the same task -> skip switch |
65 | @@: |
49 | |
66 | ; mov byte[DONT_SWITCH], 1 |
- | |
67 | call do_change_task |
50 | call do_change_task |
68 | .return: |
51 | .return: |
69 | popad |
52 | popad |
70 | popfd |
53 | popfd |
71 | ret |
54 | ret |
72 | 55 | ||
73 | uglobal |
56 | uglobal |
74 | align 4 |
57 | align 4 |
75 | ; far_jump: |
58 | ; far_jump: |
76 | ; .offs dd ? |
59 | ; .offs dd ? |
77 | ; .sel dw ? |
60 | ; .sel dw ? |
78 | context_counter dd 0 ;noname & halyavin |
61 | context_counter dd 0 ;noname & halyavin |
79 | next_usage_update dd 0 |
62 | next_usage_update dd 0 |
80 | timer_ticks dd 0 |
63 | timer_ticks dd 0 |
81 | ; prev_slot dd ? |
64 | ; prev_slot dd ? |
82 | ; event_sched dd ? |
65 | ; event_sched dd ? |
83 | endg |
66 | endg |
84 | 67 | ||
85 | align 4 |
68 | align 4 |
86 | update_counters: |
69 | update_counters: |
87 | mov edi, [TASK_BASE] |
70 | mov edi, [TASK_BASE] |
88 | rdtsc |
71 | rdtsc |
89 | sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add |
72 | sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add |
90 | add [edi+TASKDATA.counter_sum], eax ; counter sum |
73 | add [edi+TASKDATA.counter_sum], eax ; counter sum |
91 | ret |
74 | ret |
92 | align 4 |
75 | align 4 |
93 | updatecputimes: |
76 | updatecputimes: |
94 | mov ecx, [TASK_COUNT] |
77 | mov ecx, [TASK_COUNT] |
95 | mov edi, TASK_DATA |
78 | mov edi, TASK_DATA |
96 | .newupdate: |
79 | .newupdate: |
97 | xor eax, eax |
80 | xor eax, eax |
98 | xchg eax, [edi+TASKDATA.counter_sum] |
81 | xchg eax, [edi+TASKDATA.counter_sum] |
99 | mov [edi+TASKDATA.cpu_usage], eax |
82 | mov [edi+TASKDATA.cpu_usage], eax |
100 | add edi, 0x20 |
83 | add edi, 0x20 |
101 | loop .newupdate |
84 | loop .newupdate |
102 | ret |
85 | ret |
103 | 86 | ||
104 | ;TODO: Надо бы убрать использование do_change_task из V86... |
87 | ;TODO: Надо бы убрать использование do_change_task из V86... |
105 | ; и после этого перенести обработку TASKDATA.counter_add/sum в do_change_task |
88 | ; и после этого перенести обработку TASKDATA.counter_add/sum в do_change_task |
106 | 89 | ||
107 | align 4 |
90 | align 4 |
108 | do_change_task: |
91 | do_change_task: |
109 | ;param: |
92 | ;param: |
110 | ; ebx = address of the APPDATA for incoming task (new) |
93 | ; ebx = address of the APPDATA for incoming task (new) |
111 | ;warning: |
94 | ;warning: |
112 | ; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) |
95 | ; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) |
113 | ; [current_slot] is the outcoming (old), and set here to a new value (ebx) |
96 | ; [current_slot] is the outcoming (old), and set here to a new value (ebx) |
114 | ;scratched: eax,ecx,esi |
97 | ;scratched: eax,ecx,esi |
115 | mov esi, ebx |
98 | mov esi, ebx |
116 | xchg esi, [current_slot] |
99 | xchg esi, [current_slot] |
117 | ; set new stack after saving old |
100 | ; set new stack after saving old |
118 | mov [esi+APPDATA.saved_esp], esp |
101 | mov [esi+APPDATA.saved_esp], esp |
119 | mov esp, [ebx+APPDATA.saved_esp] |
102 | mov esp, [ebx+APPDATA.saved_esp] |
120 | ; set new thread io-map |
103 | ; set new thread io-map |
121 | Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map] |
104 | Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map] |
122 | Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4] |
105 | Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4] |
123 | ; set new thread memory-map |
106 | ; set new thread memory-map |
124 | mov ecx, APPDATA.dir_table |
107 | mov ecx, APPDATA.dir_table |
125 | mov eax, [ebx+ecx] ;offset>0x7F |
108 | mov eax, [ebx+ecx] ;offset>0x7F |
126 | cmp eax, [esi+ecx] ;offset>0x7F |
109 | cmp eax, [esi+ecx] ;offset>0x7F |
127 | je @f |
110 | je @f |
128 | mov cr3, eax |
111 | mov cr3, eax |
129 | @@: |
112 | @@: |
130 | ; set tss.esp0 |
113 | ; set tss.esp0 |
131 | 114 | ||
132 | Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] |
115 | Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] |
133 | 116 | ||
134 | mov edx, [ebx+APPDATA.tls_base] |
117 | mov edx, [ebx+APPDATA.tls_base] |
135 | cmp edx, [esi+APPDATA.tls_base] |
118 | cmp edx, [esi+APPDATA.tls_base] |
136 | je @f |
119 | je @f |
137 | 120 | ||
138 | mov [tls_data_l+2], dx |
121 | mov [tls_data_l+2], dx |
139 | shr edx, 16 |
122 | shr edx, 16 |
140 | mov [tls_data_l+4], dl |
123 | mov [tls_data_l+4], dl |
141 | mov [tls_data_l+7], dh |
124 | mov [tls_data_l+7], dh |
142 | 125 | ||
143 | mov dx, app_tls |
126 | mov dx, app_tls |
144 | mov fs, dx |
127 | mov fs, dx |
145 | @@: |
128 | @@: |
146 | ; set gs selector unconditionally |
129 | ; set gs selector unconditionally |
147 | Mov gs,ax,graph_data |
130 | Mov gs,ax,graph_data |
148 | ; set CR0.TS |
131 | ; set CR0.TS |
149 | cmp bh, byte[fpu_owner] ;bh == incoming task (new) |
132 | cmp bh, byte[fpu_owner] ;bh == incoming task (new) |
150 | clts ;clear a task switch flag |
133 | clts ;clear a task switch flag |
151 | je @f |
134 | je @f |
152 | mov eax, cr0 ;and set it again if the owner |
135 | mov eax, cr0 ;and set it again if the owner |
153 | or eax, CR0_TS ;of a fpu has changed |
136 | or eax, CR0_TS ;of a fpu has changed |
154 | mov cr0, eax |
137 | mov cr0, eax |
155 | @@: ; set context_counter (only for user pleasure ???) |
138 | @@: ; set context_counter (only for user pleasure ???) |
156 | inc [context_counter] ;noname & halyavin |
139 | inc [context_counter] ;noname & halyavin |
157 | ; set debug-registers, if it's necessary |
140 | ; set debug-registers, if it's necessary |
158 | test byte[ebx+APPDATA.dbg_state], 1 |
141 | test byte[ebx+APPDATA.dbg_state], 1 |
159 | jz @f |
142 | jz @f |
160 | xor eax, eax |
143 | xor eax, eax |
161 | mov dr6, eax |
144 | mov dr6, eax |
162 | lea esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F |
145 | lea esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F |
163 | cld |
146 | cld |
164 | macro lodsReg [reg] { |
147 | macro lodsReg [reg] { |
165 | lodsd |
148 | lodsd |
166 | mov reg, eax |
149 | mov reg, eax |
167 | } lodsReg dr0, dr1, dr2, dr3, dr7 |
150 | } lodsReg dr0, dr1, dr2, dr3, dr7 |
168 | purge lodsReg |
151 | purge lodsReg |
169 | @@: |
152 | @@: |
170 | ret |
153 | ret |
171 | ;end. |
154 | ;end. |
172 | 155 | ||
173 | 156 | ||
174 | 157 | ||
175 | struct MUTEX_WAITER |
158 | struct MUTEX_WAITER |
176 | list LHEAD |
159 | list LHEAD |
177 | task dd ? |
160 | task dd ? |
178 | ends |
161 | ends |
179 | 162 | ||
180 | ;void __fastcall mutex_init(struct mutex *lock) |
163 | ;void __fastcall mutex_init(struct mutex *lock) |
181 | 164 | ||
182 | align 4 |
165 | align 4 |
183 | mutex_init: |
166 | mutex_init: |
184 | mov [ecx+MUTEX.lhead.next], ecx |
167 | mov [ecx+MUTEX.lhead.next], ecx |
185 | mov [ecx+MUTEX.lhead.prev], ecx |
168 | mov [ecx+MUTEX.lhead.prev], ecx |
186 | mov [ecx+MUTEX.count], 1 |
169 | mov [ecx+MUTEX.count], 1 |
187 | ret |
170 | ret |
188 | 171 | ||
189 | 172 | ||
190 | ;void __fastcall mutex_lock(struct mutex *lock) |
173 | ;void __fastcall mutex_lock(struct mutex *lock) |
191 | 174 | ||
192 | align 4 |
175 | align 4 |
193 | mutex_lock: |
176 | mutex_lock: |
194 | 177 | ||
195 | dec [ecx+MUTEX.count] |
178 | dec [ecx+MUTEX.count] |
196 | jns .done |
179 | jns .done |
197 | 180 | ||
198 | pushfd |
181 | pushfd |
199 | cli |
182 | cli |
200 | 183 | ||
201 | sub esp, sizeof.MUTEX_WAITER |
184 | sub esp, sizeof.MUTEX_WAITER |
202 | 185 | ||
203 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
186 | list_add_tail esp, ecx ;esp= new waiter, ecx= list head |
204 | 187 | ||
205 | mov edx, [TASK_BASE] |
188 | mov edx, [TASK_BASE] |
206 | mov [esp+MUTEX_WAITER.task], edx |
189 | mov [esp+MUTEX_WAITER.task], edx |
207 | 190 | ||
208 | .forever: |
191 | .forever: |
209 | 192 | ||
210 | mov eax, -1 |
193 | mov eax, -1 |
211 | xchg eax, [ecx+MUTEX.count] |
194 | xchg eax, [ecx+MUTEX.count] |
212 | dec eax |
195 | dec eax |
213 | jz @F |
196 | jz @F |
214 | 197 | ||
215 | mov [edx+TASKDATA.state], 1 |
198 | mov [edx+TASKDATA.state], 1 |
216 | call change_task |
199 | call change_task |
217 | jmp .forever |
200 | jmp .forever |
218 | @@: |
201 | @@: |
219 | mov edx, [esp+MUTEX_WAITER.list.next] |
202 | mov edx, [esp+MUTEX_WAITER.list.next] |
220 | mov eax, [esp+MUTEX_WAITER.list.prev] |
203 | mov eax, [esp+MUTEX_WAITER.list.prev] |
221 | 204 | ||
222 | mov [eax+MUTEX_WAITER.list.next], edx |
205 | mov [eax+MUTEX_WAITER.list.next], edx |
223 | mov [edx+MUTEX_WAITER.list.prev], eax |
206 | mov [edx+MUTEX_WAITER.list.prev], eax |
224 | cmp [ecx+MUTEX.lhead.next], ecx |
207 | cmp [ecx+MUTEX.lhead.next], ecx |
225 | jne @F |
208 | jne @F |
226 | 209 | ||
227 | mov [ecx+MUTEX.count], 0 |
210 | mov [ecx+MUTEX.count], 0 |
228 | @@: |
211 | @@: |
229 | add esp, sizeof.MUTEX_WAITER |
212 | add esp, sizeof.MUTEX_WAITER |
230 | 213 | ||
231 | popfd |
214 | popfd |
232 | .done: |
215 | .done: |
233 | ret |
216 | ret |
234 | 217 | ||
235 | ;void __fastcall mutex_unlock(struct mutex *lock) |
218 | ;void __fastcall mutex_unlock(struct mutex *lock) |
236 | 219 | ||
237 | align 4 |
220 | align 4 |
238 | mutex_unlock: |
221 | mutex_unlock: |
239 | 222 | ||
240 | pushfd |
223 | pushfd |
241 | cli |
224 | cli |
242 | 225 | ||
243 | mov eax, [ecx+MUTEX.lhead.next] |
226 | mov eax, [ecx+MUTEX.lhead.next] |
244 | cmp eax, ecx |
227 | cmp eax, ecx |
245 | mov [ecx+MUTEX.count], 1 |
228 | mov [ecx+MUTEX.count], 1 |
246 | je @F |
229 | je @F |
247 | 230 | ||
248 | mov eax, [eax+MUTEX_WAITER.task] |
231 | mov eax, [eax+MUTEX_WAITER.task] |
249 | mov [eax+TASKDATA.state], 0 |
232 | mov [eax+TASKDATA.state], 0 |
250 | @@: |
233 | @@: |
251 | popfd |
234 | popfd |
252 | ret |
235 | ret |
253 | 236 | ||
254 | 237 | ||
255 | purge MUTEX_WAITER |
238 | purge MUTEX_WAITER |
256 | 239 | ||
257 | MAX_PRIORITY = 0 ; highest, used for kernel tasks |
240 | MAX_PRIORITY = 0 ; highest, used for kernel tasks |
258 | USER_PRIORITY = 1 ; default |
241 | USER_PRIORITY = 1 ; default |
259 | IDLE_PRIORITY = 2 ; lowest, only IDLE thread goes here |
242 | IDLE_PRIORITY = 2 ; lowest, only IDLE thread goes here |
260 | NR_SCHED_QUEUES = 3 ; MUST equal IDLE_PRIORYTY + 1 |
243 | NR_SCHED_QUEUES = 3 ; MUST equal IDLE_PRIORYTY + 1 |
261 | 244 | ||
262 | uglobal |
245 | uglobal |
263 | ; [scheduler_current + i*4] = zero if there are no threads with priority i, |
246 | ; [scheduler_current + i*4] = zero if there are no threads with priority i, |
264 | ; pointer to APPDATA of the current thread with priority i otherwise. |
247 | ; pointer to APPDATA of the current thread with priority i otherwise. |
265 | align 4 |
248 | align 4 |
266 | scheduler_current rd NR_SCHED_QUEUES |
249 | scheduler_current rd NR_SCHED_QUEUES |
267 | endg |
250 | endg |
268 | 251 | ||
269 | ; Add the given thread to the given priority list for the scheduler. |
252 | ; Add the given thread to the given priority list for the scheduler. |
270 | ; in: edx -> APPDATA, ecx = priority |
253 | ; in: edx -> APPDATA, ecx = priority |
271 | proc scheduler_add_thread |
254 | proc scheduler_add_thread |
272 | ; 1. Acquire the lock. |
255 | ; 1. Acquire the lock. |
273 | spin_lock_irqsave SchedulerLock |
256 | spin_lock_irqsave SchedulerLock |
274 | ; 2. Store the priority in APPDATA structure. |
257 | ; 2. Store the priority in APPDATA structure. |
275 | mov [edx+APPDATA.priority], ecx |
258 | mov [edx+APPDATA.priority], ecx |
276 | ; 3. There are two different cases: the given list is empty or not empty. |
259 | ; 3. There are two different cases: the given list is empty or not empty. |
277 | ; In first case, go to 6. Otherwise, advance to 4. |
260 | ; In first case, go to 6. Otherwise, advance to 4. |
278 | mov eax, [scheduler_current+ecx*4] |
261 | mov eax, [scheduler_current+ecx*4] |
279 | test eax, eax |
262 | test eax, eax |
280 | jz .new_list |
263 | jz .new_list |
281 | ; 4. Insert the new item immediately before the current item. |
264 | ; 4. Insert the new item immediately before the current item. |
282 | mov ecx, [eax+APPDATA.in_schedule.prev] |
265 | mov ecx, [eax+APPDATA.in_schedule.prev] |
283 | mov [edx+APPDATA.in_schedule.next], eax |
266 | mov [edx+APPDATA.in_schedule.next], eax |
284 | mov [edx+APPDATA.in_schedule.prev], ecx |
267 | mov [edx+APPDATA.in_schedule.prev], ecx |
285 | mov [eax+APPDATA.in_schedule.prev], edx |
268 | mov [eax+APPDATA.in_schedule.prev], edx |
286 | mov [ecx+APPDATA.in_schedule.next], edx |
269 | mov [ecx+APPDATA.in_schedule.next], edx |
287 | ; 5. Release the lock and return. |
270 | ; 5. Release the lock and return. |
288 | spin_unlock_irqrestore SchedulerLock |
271 | spin_unlock_irqrestore SchedulerLock |
289 | ret |
272 | ret |
290 | .new_list: |
273 | .new_list: |
291 | ; 6. Initialize the list with one item and make it the current item. |
274 | ; 6. Initialize the list with one item and make it the current item. |
292 | mov [edx+APPDATA.in_schedule.next], edx |
275 | mov [edx+APPDATA.in_schedule.next], edx |
293 | mov [edx+APPDATA.in_schedule.prev], edx |
276 | mov [edx+APPDATA.in_schedule.prev], edx |
294 | mov [scheduler_current+ecx*4], edx |
277 | mov [scheduler_current+ecx*4], edx |
295 | ; 7. Release the lock and return. |
278 | ; 7. Release the lock and return. |
296 | spin_unlock_irqrestore SchedulerLock |
279 | spin_unlock_irqrestore SchedulerLock |
297 | ret |
280 | ret |
298 | endp |
281 | endp |
299 | 282 | ||
300 | ; Remove the given thread from the corresponding priority list for the scheduler. |
283 | ; Remove the given thread from the corresponding priority list for the scheduler. |
301 | ; in: edx -> APPDATA |
284 | ; in: edx -> APPDATA |
302 | proc scheduler_remove_thread |
285 | proc scheduler_remove_thread |
303 | ; 1. Acquire the lock. |
286 | ; 1. Acquire the lock. |
304 | spin_lock_irqsave SchedulerLock |
287 | spin_lock_irqsave SchedulerLock |
305 | ; 2. Remove the item from the corresponding list. |
288 | ; 2. Remove the item from the corresponding list. |
306 | mov eax, [edx+APPDATA.in_schedule.next] |
289 | mov eax, [edx+APPDATA.in_schedule.next] |
307 | mov ecx, [edx+APPDATA.in_schedule.prev] |
290 | mov ecx, [edx+APPDATA.in_schedule.prev] |
308 | mov [eax+APPDATA.in_schedule.prev], ecx |
291 | mov [eax+APPDATA.in_schedule.prev], ecx |
309 | mov [ecx+APPDATA.in_schedule.next], eax |
292 | mov [ecx+APPDATA.in_schedule.next], eax |
310 | ; 3. If the given thread is the current item in the list, |
293 | ; 3. If the given thread is the current item in the list, |
311 | ; advance the current item. |
294 | ; advance the current item. |
312 | ; 3a. Check whether the given thread is the current item; |
295 | ; 3a. Check whether the given thread is the current item; |
313 | ; if no, skip the rest of this step. |
296 | ; if no, skip the rest of this step. |
314 | mov ecx, [edx+APPDATA.priority] |
297 | mov ecx, [edx+APPDATA.priority] |
315 | cmp [scheduler_current+ecx*4], edx |
298 | cmp [scheduler_current+ecx*4], edx |
316 | jnz .return |
299 | jnz .return |
317 | ; 3b. Set the current item to eax; step 2 has set eax = next item. |
300 | ; 3b. Set the current item to eax; step 2 has set eax = next item. |
318 | mov [scheduler_current+ecx*4], eax |
301 | mov [scheduler_current+ecx*4], eax |
319 | ; 3c. If there were only one item in the list, zero the current item. |
302 | ; 3c. If there were only one item in the list, zero the current item. |
320 | cmp eax, edx |
303 | cmp eax, edx |
321 | jnz .return |
304 | jnz .return |
322 | mov [scheduler_current+ecx*4], 0 |
305 | mov [scheduler_current+ecx*4], 0 |
323 | .return: |
306 | .return: |
324 | ; 4. Release the lock and return. |
307 | ; 4. Release the lock and return. |
325 | spin_unlock_irqrestore SchedulerLock |
308 | spin_unlock_irqrestore SchedulerLock |
326 | ret |
309 | ret |
327 | endp |
310 | endp |
328 | 311 | ||
329 | SCHEDULE_ANY_PRIORITY = 0 |
312 | SCHEDULE_ANY_PRIORITY = 0 |
330 | SCHEDULE_HIGHER_PRIORITY = 1 |
313 | SCHEDULE_HIGHER_PRIORITY = 1 |
331 | ;info: |
314 | ;info: |
332 | ; Find next task to execute |
315 | ; Find next task to execute |
333 | ;in: |
316 | ;in: |
334 | ; bl = SCHEDULE_ANY_PRIORITY: |
317 | ; bl = SCHEDULE_ANY_PRIORITY: |
335 | ; consider threads with any priority |
318 | ; consider threads with any priority |
336 | ; bl = SCHEDULE_HIGHER_PRIORITY: |
319 | ; bl = SCHEDULE_HIGHER_PRIORITY: |
337 | ; consider only threads with strictly higher priority than the current one, |
320 | ; consider only threads with strictly higher priority than the current one, |
338 | ; keep running the current thread if other ready threads have the same or lower priority |
321 | ; keep running the current thread if other ready threads have the same or lower priority |
339 | ;retval: |
322 | ;retval: |
340 | ; ebx = address of the APPDATA for the selected task (slot-base) |
323 | ; ebx = address of the APPDATA for the selected task (slot-base) |
341 | ; edi = address of the TASKDATA for the selected task |
324 | ; edi = address of the TASKDATA for the selected task |
342 | ; ZF = 1 if the task is the same |
325 | ; ZF = 1 if the task is the same |
343 | ;warning: |
326 | ;warning: |
344 | ; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result |
327 | ; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result |
345 | ; [current_slot] is not set to new value (ebx)!!! |
328 | ; [current_slot] is not set to new value (ebx)!!! |
346 | ;scratched: eax,ecx |
329 | ;scratched: eax,ecx |
347 | proc find_next_task |
330 | proc find_next_task |
348 | call update_counters |
331 | call update_counters |
349 | spin_lock_irqsave SchedulerLock |
332 | spin_lock_irqsave SchedulerLock |
350 | push NR_SCHED_QUEUES |
333 | push NR_SCHED_QUEUES |
351 | ; If bl == SCHEDULE_ANY_PRIORITY = 0, loop over all NR_SCHED lists. |
334 | ; If bl == SCHEDULE_ANY_PRIORITY = 0, loop over all NR_SCHED lists. |
352 | ; Otherwise, loop over first [APPDATA.priority] lists. |
335 | ; Otherwise, loop over first [APPDATA.priority] lists. |
353 | test bl, bl |
336 | test bl, bl |
354 | jz .start |
337 | jz .start |
355 | mov ebx, [current_slot] |
338 | mov ebx, [current_slot] |
356 | mov edi, [TASK_BASE] |
339 | mov edi, [TASK_BASE] |
357 | mov eax, [ebx+APPDATA.priority] |
340 | mov eax, [ebx+APPDATA.priority] |
358 | test eax, eax |
341 | test eax, eax |
359 | jz .unlock_found |
342 | jz .unlock_found |
360 | mov [esp], eax |
343 | mov [esp], eax |
361 | .start: |
344 | .start: |
362 | xor ecx, ecx |
345 | xor ecx, ecx |
363 | .priority_loop: |
346 | .priority_loop: |
364 | mov ebx, [scheduler_current+ecx*4] |
347 | mov ebx, [scheduler_current+ecx*4] |
365 | test ebx, ebx |
348 | test ebx, ebx |
366 | jz .priority_next |
349 | jz .priority_next |
367 | .task_loop: |
350 | .task_loop: |
368 | mov ebx, [ebx+APPDATA.in_schedule.next] |
351 | mov ebx, [ebx+APPDATA.in_schedule.next] |
369 | mov edi, ebx |
352 | mov edi, ebx |
370 | shr edi, 3 |
353 | shr edi, 3 |
371 | add edi, CURRENT_TASK - (SLOT_BASE shr 3) |
354 | add edi, CURRENT_TASK - (SLOT_BASE shr 3) |
372 | mov al, [edi+TASKDATA.state] |
355 | mov al, [edi+TASKDATA.state] |
373 | test al, al |
356 | test al, al |
374 | jz .task_found ; state == 0 |
357 | jz .task_found ; state == 0 |
375 | cmp al, 5 |
358 | cmp al, 5 |
376 | jne .task_next ; state == 1,2,3,4,9 |
359 | jne .task_next ; state == 1,2,3,4,9 |
377 | ; state == 5 |
360 | ; state == 5 |
378 | pushad ; more freedom for [APPDATA.wait_test] |
361 | pushad ; more freedom for [APPDATA.wait_test] |
379 | call [ebx+APPDATA.wait_test] |
362 | call [ebx+APPDATA.wait_test] |
380 | mov [esp+28], eax |
363 | mov [esp+28], eax |
381 | popad |
364 | popad |
382 | or eax, eax |
365 | or eax, eax |
383 | jnz @f |
366 | jnz @f |
384 | ; testing for timeout |
367 | ; testing for timeout |
385 | mov eax, [timer_ticks] |
368 | mov eax, [timer_ticks] |
386 | sub eax, [ebx+APPDATA.wait_begin] |
369 | sub eax, [ebx+APPDATA.wait_begin] |
387 | cmp eax, [ebx+APPDATA.wait_timeout] |
370 | cmp eax, [ebx+APPDATA.wait_timeout] |
388 | jb .task_next |
371 | jb .task_next |
389 | xor eax, eax |
372 | xor eax, eax |
390 | @@: |
373 | @@: |
391 | mov [ebx+APPDATA.wait_param], eax ; retval for wait |
374 | mov [ebx+APPDATA.wait_param], eax ; retval for wait |
392 | mov [edi+TASKDATA.state], 0 |
375 | mov [edi+TASKDATA.state], 0 |
393 | .task_found: |
376 | .task_found: |
394 | mov [scheduler_current+ecx*4], ebx |
377 | mov [scheduler_current+ecx*4], ebx |
395 | ; If we have selected a thread with higher priority |
378 | ; If we have selected a thread with higher priority |
396 | ; AND rescheduling is due to IRQ, |
379 | ; AND rescheduling is due to IRQ, |
397 | ; turn the current scheduler list one entry back, |
380 | ; turn the current scheduler list one entry back, |
398 | ; so the current thread will be next after high-priority thread is done. |
381 | ; so the current thread will be next after high-priority thread is done. |
399 | mov ecx, [esp] |
382 | mov ecx, [esp] |
400 | cmp ecx, NR_SCHED_QUEUES |
383 | cmp ecx, NR_SCHED_QUEUES |
401 | jz .unlock_found |
384 | jz .unlock_found |
402 | mov eax, [current_slot] |
385 | mov eax, [current_slot] |
403 | mov eax, [eax+APPDATA.in_schedule.prev] |
386 | mov eax, [eax+APPDATA.in_schedule.prev] |
404 | mov [scheduler_current+ecx*4], eax |
387 | mov [scheduler_current+ecx*4], eax |
405 | .unlock_found: |
388 | .unlock_found: |
406 | pop ecx |
389 | pop ecx |
407 | spin_unlock_irqrestore SchedulerLock |
390 | spin_unlock_irqrestore SchedulerLock |
408 | .found: |
391 | .found: |
409 | mov [CURRENT_TASK], bh |
392 | mov [CURRENT_TASK], bh |
410 | mov [TASK_BASE], edi |
393 | mov [TASK_BASE], edi |
411 | rdtsc ;call _rdtsc |
394 | rdtsc ;call _rdtsc |
412 | mov [edi+TASKDATA.counter_add], eax; for next using update_counters |
395 | mov [edi+TASKDATA.counter_add], eax; for next using update_counters |
413 | cmp ebx, [current_slot] |
396 | cmp ebx, [current_slot] |
414 | ret |
397 | ret |
415 | .task_next: |
398 | .task_next: |
416 | cmp ebx, [scheduler_current+ecx*4] |
399 | cmp ebx, [scheduler_current+ecx*4] |
417 | jnz .task_loop |
400 | jnz .task_loop |
418 | .priority_next: |
401 | .priority_next: |
419 | inc ecx |
402 | inc ecx |
420 | cmp ecx, [esp] |
403 | cmp ecx, [esp] |
421 | jb .priority_loop |
404 | jb .priority_loop |
422 | mov ebx, [current_slot] |
405 | mov ebx, [current_slot] |
423 | mov edi, [TASK_BASE] |
406 | mov edi, [TASK_BASE] |
424 | jmp .unlock_found |
407 | jmp .unlock_found |
425 | endp |
408 | endp |
426 | 409 | ||
427 | if 0 |
410 | if 0 |
428 | 411 | ||
429 | struc TIMER |
412 | struc TIMER |
430 | { |
413 | { |
431 | .next dd ? |
414 | .next dd ? |
432 | .exp_time dd ? |
415 | .exp_time dd ? |
433 | .func dd ? |
416 | .func dd ? |
434 | .arg dd ? |
417 | .arg dd ? |
435 | } |
418 | } |
436 | 419 | ||
437 | 420 | ||
438 | uglobal |
421 | uglobal |
439 | rdy_head rd 16 |
422 | rdy_head rd 16 |
440 | endg |
423 | endg |
441 | 424 | ||
442 | align 4 |
425 | align 4 |
443 | pick_task: |
426 | pick_task: |
444 | 427 | ||
445 | xor eax, eax |
428 | xor eax, eax |
446 | .pick: |
429 | .pick: |
447 | mov ebx, [rdy_head+eax*4] |
430 | mov ebx, [rdy_head+eax*4] |
448 | test ebx, ebx |
431 | test ebx, ebx |
449 | jz .next |
432 | jz .next |
450 | 433 | ||
451 | mov [next_task], ebx |
434 | mov [next_task], ebx |
452 | test [ebx+flags.billable] |
435 | test [ebx+flags.billable] |
453 | jz @F |
436 | jz @F |
454 | mov [bill_task], ebx |
437 | mov [bill_task], ebx |
455 | @@: |
438 | @@: |
456 | ret |
439 | ret |
457 | .next: |
440 | .next: |
458 | inc eax |
441 | inc eax |
459 | jmp .pick |
442 | jmp .pick |
460 | 443 | ||
461 | ; param |
444 | ; param |
462 | ; eax= task |
445 | ; eax= task |
463 | ; |
446 | ; |
464 | ; retval |
447 | ; retval |
465 | ; eax= task |
448 | ; eax= task |
466 | ; ebx= queue |
449 | ; ebx= queue |
467 | ; ecx= front if 1 or back if 0 |
450 | ; ecx= front if 1 or back if 0 |
468 | align 4 |
451 | align 4 |
469 | shed: |
452 | shed: |
470 | cmp [eax+.tics_left], 0;signed compare |
453 | cmp [eax+.tics_left], 0;signed compare |
471 | mov ebx, [eax+.priority] |
454 | mov ebx, [eax+.priority] |
472 | setg ecx |
455 | setg ecx |
473 | jg @F |
456 | jg @F |
474 | 457 | ||
475 | mov edx, [eax+.tics_quantum] |
458 | mov edx, [eax+.tics_quantum] |
476 | mov [eax+.ticks_left], edx |
459 | mov [eax+.ticks_left], edx |
477 | cmp ebx, (IDLE_PRIORITY-1) |
460 | cmp ebx, (IDLE_PRIORITY-1) |
478 | je @F |
461 | je @F |
479 | inc ebx |
462 | inc ebx |
480 | @@: |
463 | @@: |
481 | ret |
464 | ret |
482 | 465 | ||
483 | ; param |
466 | ; param |
484 | ; eax= task |
467 | ; eax= task |
485 | align 4 |
468 | align 4 |
486 | enqueue: |
469 | enqueue: |
487 | call shed;eax |
470 | call shed;eax |
488 | cmp [rdy_head+ebx*4], 0 |
471 | cmp [rdy_head+ebx*4], 0 |
489 | jnz @F |
472 | jnz @F |
490 | 473 | ||
491 | mov [rdy_head+ebx*4], eax |
474 | mov [rdy_head+ebx*4], eax |
492 | mov [rdy_tail+ebx*4], eax |
475 | mov [rdy_tail+ebx*4], eax |
493 | mov [eax+.next_ready], 0 |
476 | mov [eax+.next_ready], 0 |
494 | jmp .pick |
477 | jmp .pick |
495 | @@: |
478 | @@: |
496 | test ecx, ecx |
479 | test ecx, ecx |
497 | jz .back |
480 | jz .back |
498 | 481 | ||
499 | mov ecx, [rdy_head+ebx*4] |
482 | mov ecx, [rdy_head+ebx*4] |
500 | mov [eax+.next_ready], ecx |
483 | mov [eax+.next_ready], ecx |
501 | mov [rdy_head+ebx*4], eax |
484 | mov [rdy_head+ebx*4], eax |
502 | jmp .pick |
485 | jmp .pick |
503 | .back: |
486 | .back: |
504 | mov ecx, [rdy_tail+ebx*4] |
487 | mov ecx, [rdy_tail+ebx*4] |
505 | mov [ecx+.next_ready], eax |
488 | mov [ecx+.next_ready], eax |
506 | mov [rdy_tail+ebx*4], eax |
489 | mov [rdy_tail+ebx*4], eax |
507 | mov [eax+.next_ready], 0 |
490 | mov [eax+.next_ready], 0 |
508 | .pick: |
491 | .pick: |
509 | call pick_proc;select next task |
492 | call pick_proc;select next task |
510 | ret |
493 | ret |
511 | 494 | ||
512 | end if->---><---><<---> |
495 | end if---><---><<---> |