Subversion Repositories Kolibri OS

Rev

Rev 4432 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4432 Rev 4923
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: 3617 $
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     eax, [ebx+APPDATA.process]
107
        mov     eax, [ebx+APPDATA.process]
125
        cmp     eax, [current_process]
108
        cmp     eax, [current_process]
126
        je      @f
109
        je      @f
127
        mov     [current_process], eax
110
        mov     [current_process], eax
128
        mov     eax, [eax+PROC.pdt_0_phys]
111
        mov     eax, [eax+PROC.pdt_0_phys]
129
        mov     cr3, eax
112
        mov     cr3, eax
130
@@:
113
@@:
131
; set tss.esp0
114
; set tss.esp0
132
 
115
 
133
        Mov     [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
116
        Mov     [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
134
 
117
 
135
        mov     edx, [ebx+APPDATA.tls_base]
118
        mov     edx, [ebx+APPDATA.tls_base]
136
        cmp     edx, [esi+APPDATA.tls_base]
119
        cmp     edx, [esi+APPDATA.tls_base]
137
        je      @f
120
        je      @f
138
 
121
 
139
        mov     [tls_data_l+2], dx
122
        mov     [tls_data_l+2], dx
140
        shr     edx, 16
123
        shr     edx, 16
141
        mov     [tls_data_l+4], dl
124
        mov     [tls_data_l+4], dl
142
        mov     [tls_data_l+7], dh
125
        mov     [tls_data_l+7], dh
143
 
126
 
144
        mov     dx, app_tls
127
        mov     dx, app_tls
145
        mov     fs, dx
128
        mov     fs, dx
146
@@:
129
@@:
147
; set gs selector unconditionally
130
; set gs selector unconditionally
148
        Mov     gs,ax,graph_data
131
        Mov     gs,ax,graph_data
149
      ; set CR0.TS
132
      ; set CR0.TS
150
        cmp     bh, byte[fpu_owner] ;bh == incoming task (new)
133
        cmp     bh, byte[fpu_owner] ;bh == incoming task (new)
151
        clts                        ;clear a task switch flag
134
        clts                        ;clear a task switch flag
152
        je      @f
135
        je      @f
153
        mov     eax, cr0            ;and set it again if the owner
136
        mov     eax, cr0            ;and set it again if the owner
154
        or      eax, CR0_TS         ;of a fpu has changed
137
        or      eax, CR0_TS         ;of a fpu has changed
155
        mov     cr0, eax
138
        mov     cr0, eax
156
  @@: ; set context_counter (only for user pleasure ???)
139
  @@: ; set context_counter (only for user pleasure ???)
157
        inc     [context_counter]   ;noname & halyavin
140
        inc     [context_counter]   ;noname & halyavin
158
      ; set debug-registers, if it's necessary
141
      ; set debug-registers, if it's necessary
159
        test    byte[ebx+APPDATA.dbg_state], 1
142
        test    byte[ebx+APPDATA.dbg_state], 1
160
        jz      @f
143
        jz      @f
161
        xor     eax, eax
144
        xor     eax, eax
162
        mov     dr6, eax
145
        mov     dr6, eax
163
        lea     esi, [ebx+APPDATA.dbg_regs]
146
        lea     esi, [ebx+APPDATA.dbg_regs]
164
        cld
147
        cld
165
  macro lodsReg [reg] {
148
  macro lodsReg [reg] {
166
        lodsd
149
        lodsd
167
        mov     reg, eax
150
        mov     reg, eax
168
  }     lodsReg dr0, dr1, dr2, dr3, dr7
151
  }     lodsReg dr0, dr1, dr2, dr3, dr7
169
  purge lodsReg
152
  purge lodsReg
170
  @@:
153
  @@:
171
        ret
154
        ret
172
;end.
155
;end.
173
 
156
 
174
 
157
 
175
 
158
 
176
struct  MUTEX_WAITER
159
struct  MUTEX_WAITER
177
        list    LHEAD
160
        list    LHEAD
178
        task    dd ?
161
        task    dd ?
179
ends
162
ends
180
 
163
 
181
;void  __fastcall mutex_init(struct mutex *lock)
164
;void  __fastcall mutex_init(struct mutex *lock)
182
 
165
 
183
align 4
166
align 4
184
mutex_init:
167
mutex_init:
185
        mov     [ecx+MUTEX.lhead.next], ecx
168
        mov     [ecx+MUTEX.lhead.next], ecx
186
        mov     [ecx+MUTEX.lhead.prev], ecx
169
        mov     [ecx+MUTEX.lhead.prev], ecx
187
        mov     [ecx+MUTEX.count], 1
170
        mov     [ecx+MUTEX.count], 1
188
        ret
171
        ret
189
 
172
 
190
 
173
 
191
;void  __fastcall mutex_lock(struct mutex *lock)
174
;void  __fastcall mutex_lock(struct mutex *lock)
192
 
175
 
193
align 4
176
align 4
194
mutex_lock:
177
mutex_lock:
195
 
178
 
196
        dec     [ecx+MUTEX.count]
179
        dec     [ecx+MUTEX.count]
197
        jns     .done
180
        jns     .done
198
 
181
 
199
        pushfd
182
        pushfd
200
        cli
183
        cli
201
 
184
 
202
        sub     esp, sizeof.MUTEX_WAITER
185
        sub     esp, sizeof.MUTEX_WAITER
203
 
186
 
204
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
187
        list_add_tail esp, ecx      ;esp= new waiter, ecx= list head
205
 
188
 
206
        mov     edx, [TASK_BASE]
189
        mov     edx, [TASK_BASE]
207
        mov     [esp+MUTEX_WAITER.task], edx
190
        mov     [esp+MUTEX_WAITER.task], edx
208
 
191
 
209
.forever:
192
.forever:
210
 
193
 
211
        mov     eax, -1
194
        mov     eax, -1
212
        xchg    eax, [ecx+MUTEX.count]
195
        xchg    eax, [ecx+MUTEX.count]
213
        dec     eax
196
        dec     eax
214
        jz      @F
197
        jz      @F
215
 
198
 
216
        mov     [edx+TASKDATA.state], 1
199
        mov     [edx+TASKDATA.state], 1
217
        call    change_task
200
        call    change_task
218
        jmp     .forever
201
        jmp     .forever
219
@@:
202
@@:
220
        mov     edx, [esp+MUTEX_WAITER.list.next]
203
        mov     edx, [esp+MUTEX_WAITER.list.next]
221
        mov     eax, [esp+MUTEX_WAITER.list.prev]
204
        mov     eax, [esp+MUTEX_WAITER.list.prev]
222
 
205
 
223
        mov     [eax+MUTEX_WAITER.list.next], edx
206
        mov     [eax+MUTEX_WAITER.list.next], edx
224
        mov     [edx+MUTEX_WAITER.list.prev], eax
207
        mov     [edx+MUTEX_WAITER.list.prev], eax
225
        cmp     [ecx+MUTEX.lhead.next], ecx
208
        cmp     [ecx+MUTEX.lhead.next], ecx
226
        jne     @F
209
        jne     @F
227
 
210
 
228
        mov     [ecx+MUTEX.count], 0
211
        mov     [ecx+MUTEX.count], 0
229
@@:
212
@@:
230
        add     esp, sizeof.MUTEX_WAITER
213
        add     esp, sizeof.MUTEX_WAITER
231
 
214
 
232
        popfd
215
        popfd
233
.done:
216
.done:
234
        ret
217
        ret
235
 
218
 
236
;void  __fastcall mutex_unlock(struct mutex *lock)
219
;void  __fastcall mutex_unlock(struct mutex *lock)
237
 
220
 
238
align 4
221
align 4
239
mutex_unlock:
222
mutex_unlock:
240
 
223
 
241
        pushfd
224
        pushfd
242
        cli
225
        cli
243
 
226
 
244
        mov     eax, [ecx+MUTEX.lhead.next]
227
        mov     eax, [ecx+MUTEX.lhead.next]
245
        cmp     eax, ecx
228
        cmp     eax, ecx
246
        mov     [ecx+MUTEX.count], 1
229
        mov     [ecx+MUTEX.count], 1
247
        je      @F
230
        je      @F
248
 
231
 
249
        mov     eax, [eax+MUTEX_WAITER.task]
232
        mov     eax, [eax+MUTEX_WAITER.task]
250
        mov     [eax+TASKDATA.state], 0
233
        mov     [eax+TASKDATA.state], 0
251
@@:
234
@@:
252
        popfd
235
        popfd
253
        ret
236
        ret
254
 
237
 
255
 
238
 
256
purge MUTEX_WAITER
239
purge MUTEX_WAITER
257
 
240
 
258
MAX_PRIORITY      = 0   ; highest, used for kernel tasks
241
MAX_PRIORITY      = 0   ; highest, used for kernel tasks
259
USER_PRIORITY     = 1   ; default
242
USER_PRIORITY     = 1   ; default
260
IDLE_PRIORITY     = 2   ; lowest, only IDLE thread goes here
243
IDLE_PRIORITY     = 2   ; lowest, only IDLE thread goes here
261
NR_SCHED_QUEUES   = 3   ; MUST equal IDLE_PRIORYTY + 1
244
NR_SCHED_QUEUES   = 3   ; MUST equal IDLE_PRIORYTY + 1
262
 
245
 
263
uglobal
246
uglobal
264
; [scheduler_current + i*4] = zero if there are no threads with priority i,
247
; [scheduler_current + i*4] = zero if there are no threads with priority i,
265
;  pointer to APPDATA of the current thread with priority i otherwise.
248
;  pointer to APPDATA of the current thread with priority i otherwise.
266
align 4
249
align 4
267
scheduler_current       rd      NR_SCHED_QUEUES
250
scheduler_current       rd      NR_SCHED_QUEUES
268
endg
251
endg
269
 
252
 
270
; Add the given thread to the given priority list for the scheduler.
253
; Add the given thread to the given priority list for the scheduler.
271
; in: edx -> APPDATA, ecx = priority
254
; in: edx -> APPDATA, ecx = priority
272
proc scheduler_add_thread
255
proc scheduler_add_thread
273
; 1. Acquire the lock.
256
; 1. Acquire the lock.
274
        spin_lock_irqsave SchedulerLock
257
        spin_lock_irqsave SchedulerLock
275
; 2. Store the priority in APPDATA structure.
258
; 2. Store the priority in APPDATA structure.
276
        mov     [edx+APPDATA.priority], ecx
259
        mov     [edx+APPDATA.priority], ecx
277
; 3. There are two different cases: the given list is empty or not empty.
260
; 3. There are two different cases: the given list is empty or not empty.
278
; In first case, go to 6. Otherwise, advance to 4.
261
; In first case, go to 6. Otherwise, advance to 4.
279
        mov     eax, [scheduler_current+ecx*4]
262
        mov     eax, [scheduler_current+ecx*4]
280
        test    eax, eax
263
        test    eax, eax
281
        jz      .new_list
264
        jz      .new_list
282
; 4. Insert the new item immediately before the current item.
265
; 4. Insert the new item immediately before the current item.
283
        mov     ecx, [eax+APPDATA.in_schedule.prev]
266
        mov     ecx, [eax+APPDATA.in_schedule.prev]
284
        mov     [edx+APPDATA.in_schedule.next], eax
267
        mov     [edx+APPDATA.in_schedule.next], eax
285
        mov     [edx+APPDATA.in_schedule.prev], ecx
268
        mov     [edx+APPDATA.in_schedule.prev], ecx
286
        mov     [eax+APPDATA.in_schedule.prev], edx
269
        mov     [eax+APPDATA.in_schedule.prev], edx
287
        mov     [ecx+APPDATA.in_schedule.next], edx
270
        mov     [ecx+APPDATA.in_schedule.next], edx
288
; 5. Release the lock and return.
271
; 5. Release the lock and return.
289
        spin_unlock_irqrestore SchedulerLock
272
        spin_unlock_irqrestore SchedulerLock
290
        ret
273
        ret
291
.new_list:
274
.new_list:
292
; 6. Initialize the list with one item and make it the current item.
275
; 6. Initialize the list with one item and make it the current item.
293
        mov     [edx+APPDATA.in_schedule.next], edx
276
        mov     [edx+APPDATA.in_schedule.next], edx
294
        mov     [edx+APPDATA.in_schedule.prev], edx
277
        mov     [edx+APPDATA.in_schedule.prev], edx
295
        mov     [scheduler_current+ecx*4], edx
278
        mov     [scheduler_current+ecx*4], edx
296
; 7. Release the lock and return.
279
; 7. Release the lock and return.
297
        spin_unlock_irqrestore SchedulerLock
280
        spin_unlock_irqrestore SchedulerLock
298
        ret
281
        ret
299
endp
282
endp
300
 
283
 
301
; Remove the given thread from the corresponding priority list for the scheduler.
284
; Remove the given thread from the corresponding priority list for the scheduler.
302
; in: edx -> APPDATA
285
; in: edx -> APPDATA
303
proc scheduler_remove_thread
286
proc scheduler_remove_thread
304
; 1. Acquire the lock.
287
; 1. Acquire the lock.
305
        spin_lock_irqsave SchedulerLock
288
        spin_lock_irqsave SchedulerLock
306
; 2. Remove the item from the corresponding list.
289
; 2. Remove the item from the corresponding list.
307
        mov     eax, [edx+APPDATA.in_schedule.next]
290
        mov     eax, [edx+APPDATA.in_schedule.next]
308
        mov     ecx, [edx+APPDATA.in_schedule.prev]
291
        mov     ecx, [edx+APPDATA.in_schedule.prev]
309
        mov     [eax+APPDATA.in_schedule.prev], ecx
292
        mov     [eax+APPDATA.in_schedule.prev], ecx
310
        mov     [ecx+APPDATA.in_schedule.next], eax
293
        mov     [ecx+APPDATA.in_schedule.next], eax
311
; 3. If the given thread is the current item in the list,
294
; 3. If the given thread is the current item in the list,
312
; advance the current item.
295
; advance the current item.
313
; 3a. Check whether the given thread is the current item;
296
; 3a. Check whether the given thread is the current item;
314
; if no, skip the rest of this step.
297
; if no, skip the rest of this step.
315
        mov     ecx, [edx+APPDATA.priority]
298
        mov     ecx, [edx+APPDATA.priority]
316
        cmp     [scheduler_current+ecx*4], edx
299
        cmp     [scheduler_current+ecx*4], edx
317
        jnz     .return
300
        jnz     .return
318
; 3b. Set the current item to eax; step 2 has set eax = next item.
301
; 3b. Set the current item to eax; step 2 has set eax = next item.
319
        mov     [scheduler_current+ecx*4], eax
302
        mov     [scheduler_current+ecx*4], eax
320
; 3c. If there were only one item in the list, zero the current item.
303
; 3c. If there were only one item in the list, zero the current item.
321
        cmp     eax, edx
304
        cmp     eax, edx
322
        jnz     .return
305
        jnz     .return
323
        mov     [scheduler_current+ecx*4], 0
306
        mov     [scheduler_current+ecx*4], 0
324
.return:
307
.return:
325
; 4. Release the lock and return.
308
; 4. Release the lock and return.
326
        spin_unlock_irqrestore SchedulerLock
309
        spin_unlock_irqrestore SchedulerLock
327
        ret
310
        ret
328
endp
311
endp
329
 
312
 
330
SCHEDULE_ANY_PRIORITY = 0
313
SCHEDULE_ANY_PRIORITY = 0
331
SCHEDULE_HIGHER_PRIORITY = 1
314
SCHEDULE_HIGHER_PRIORITY = 1
332
;info:
315
;info:
333
;   Find next task to execute
316
;   Find next task to execute
334
;in:
317
;in:
335
;   bl = SCHEDULE_ANY_PRIORITY:
318
;   bl = SCHEDULE_ANY_PRIORITY:
336
;        consider threads with any priority
319
;        consider threads with any priority
337
;   bl = SCHEDULE_HIGHER_PRIORITY:
320
;   bl = SCHEDULE_HIGHER_PRIORITY:
338
;        consider only threads with strictly higher priority than the current one,
321
;        consider only threads with strictly higher priority than the current one,
339
;        keep running the current thread if other ready threads have the same or lower priority
322
;        keep running the current thread if other ready threads have the same or lower priority
340
;retval:
323
;retval:
341
;   ebx = address of the APPDATA for the selected task (slot-base)
324
;   ebx = address of the APPDATA for the selected task (slot-base)
342
;   edi = address of the TASKDATA for the selected task
325
;   edi = address of the TASKDATA for the selected task
343
;   ZF  = 1  if the task is the same
326
;   ZF  = 1  if the task is the same
344
;warning:
327
;warning:
345
;   [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
328
;   [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
346
;   [current_slot] is not set to new value (ebx)!!!
329
;   [current_slot] is not set to new value (ebx)!!!
347
;scratched: eax,ecx
330
;scratched: eax,ecx
348
proc find_next_task
331
proc find_next_task
349
        call    update_counters
332
        call    update_counters
350
        spin_lock_irqsave SchedulerLock
333
        spin_lock_irqsave SchedulerLock
351
        push    NR_SCHED_QUEUES
334
        push    NR_SCHED_QUEUES
352
; If bl == SCHEDULE_ANY_PRIORITY = 0, loop over all NR_SCHED lists.
335
; If bl == SCHEDULE_ANY_PRIORITY = 0, loop over all NR_SCHED lists.
353
; Otherwise, loop over first [APPDATA.priority] lists.
336
; Otherwise, loop over first [APPDATA.priority] lists.
354
        test    bl, bl
337
        test    bl, bl
355
        jz      .start
338
        jz      .start
356
        mov     ebx, [current_slot]
339
        mov     ebx, [current_slot]
357
        mov     edi, [TASK_BASE]
340
        mov     edi, [TASK_BASE]
358
        mov     eax, [ebx+APPDATA.priority]
341
        mov     eax, [ebx+APPDATA.priority]
359
        test    eax, eax
342
        test    eax, eax
360
        jz      .unlock_found
343
        jz      .unlock_found
361
        mov     [esp], eax
344
        mov     [esp], eax
362
.start:
345
.start:
363
        xor     ecx, ecx
346
        xor     ecx, ecx
364
.priority_loop:
347
.priority_loop:
365
        mov     ebx, [scheduler_current+ecx*4]
348
        mov     ebx, [scheduler_current+ecx*4]
366
        test    ebx, ebx
349
        test    ebx, ebx
367
        jz      .priority_next
350
        jz      .priority_next
368
.task_loop:
351
.task_loop:
369
        mov     ebx, [ebx+APPDATA.in_schedule.next]
352
        mov     ebx, [ebx+APPDATA.in_schedule.next]
370
        mov     edi, ebx
353
        mov     edi, ebx
371
        shr     edi, 3
354
        shr     edi, 3
372
        add     edi, CURRENT_TASK - (SLOT_BASE shr 3)
355
        add     edi, CURRENT_TASK - (SLOT_BASE shr 3)
373
        mov     al, [edi+TASKDATA.state]
356
        mov     al, [edi+TASKDATA.state]
374
        test    al, al
357
        test    al, al
375
        jz      .task_found     ; state == 0
358
        jz      .task_found     ; state == 0
376
        cmp     al, 5
359
        cmp     al, 5
377
        jne     .task_next      ; state == 1,2,3,4,9
360
        jne     .task_next      ; state == 1,2,3,4,9
378
      ; state == 5
361
      ; state == 5
379
        pushad  ; more freedom for [APPDATA.wait_test]
362
        pushad  ; more freedom for [APPDATA.wait_test]
380
        call    [ebx+APPDATA.wait_test]
363
        call    [ebx+APPDATA.wait_test]
381
        mov     [esp+28], eax
364
        mov     [esp+28], eax
382
        popad
365
        popad
383
        or      eax, eax
366
        or      eax, eax
384
        jnz     @f
367
        jnz     @f
385
      ; testing for timeout
368
      ; testing for timeout
386
        mov     eax, [timer_ticks]
369
        mov     eax, [timer_ticks]
387
        sub     eax, [ebx+APPDATA.wait_begin]
370
        sub     eax, [ebx+APPDATA.wait_begin]
388
        cmp     eax, [ebx+APPDATA.wait_timeout]
371
        cmp     eax, [ebx+APPDATA.wait_timeout]
389
        jb      .task_next
372
        jb      .task_next
390
        xor     eax, eax
373
        xor     eax, eax
391
@@:
374
@@:
392
        mov     [ebx+APPDATA.wait_param], eax  ; retval for wait
375
        mov     [ebx+APPDATA.wait_param], eax  ; retval for wait
393
        mov     [edi+TASKDATA.state], 0
376
        mov     [edi+TASKDATA.state], 0
394
.task_found:
377
.task_found:
395
        mov     [scheduler_current+ecx*4], ebx
378
        mov     [scheduler_current+ecx*4], ebx
396
; If we have selected a thread with higher priority
379
; If we have selected a thread with higher priority
397
; AND rescheduling is due to IRQ,
380
; AND rescheduling is due to IRQ,
398
; turn the current scheduler list one entry back,
381
; turn the current scheduler list one entry back,
399
; so the current thread will be next after high-priority thread is done.
382
; so the current thread will be next after high-priority thread is done.
400
        mov     ecx, [esp]
383
        mov     ecx, [esp]
401
        cmp     ecx, NR_SCHED_QUEUES
384
        cmp     ecx, NR_SCHED_QUEUES
402
        jz      .unlock_found
385
        jz      .unlock_found
403
        mov     eax, [current_slot]
386
        mov     eax, [current_slot]
404
        mov     eax, [eax+APPDATA.in_schedule.prev]
387
        mov     eax, [eax+APPDATA.in_schedule.prev]
405
        mov     [scheduler_current+ecx*4], eax
388
        mov     [scheduler_current+ecx*4], eax
406
.unlock_found:
389
.unlock_found:
407
        pop     ecx
390
        pop     ecx
408
        spin_unlock_irqrestore SchedulerLock
391
        spin_unlock_irqrestore SchedulerLock
409
.found:
392
.found:
410
        mov     [CURRENT_TASK], bh
393
        mov     [CURRENT_TASK], bh
411
        mov     [TASK_BASE], edi
394
        mov     [TASK_BASE], edi
412
        rdtsc   ;call  _rdtsc
395
        rdtsc   ;call  _rdtsc
413
        mov     [edi+TASKDATA.counter_add], eax; for next using update_counters
396
        mov     [edi+TASKDATA.counter_add], eax; for next using update_counters
414
        cmp     ebx, [current_slot]
397
        cmp     ebx, [current_slot]
415
        ret
398
        ret
416
.task_next:
399
.task_next:
417
        cmp     ebx, [scheduler_current+ecx*4]
400
        cmp     ebx, [scheduler_current+ecx*4]
418
        jnz     .task_loop
401
        jnz     .task_loop
419
.priority_next:
402
.priority_next:
420
        inc     ecx
403
        inc     ecx
421
        cmp     ecx, [esp]
404
        cmp     ecx, [esp]
422
        jb      .priority_loop
405
        jb      .priority_loop
423
        mov     ebx, [current_slot]
406
        mov     ebx, [current_slot]
424
        mov     edi, [TASK_BASE]
407
        mov     edi, [TASK_BASE]
425
        jmp     .unlock_found
408
        jmp     .unlock_found
426
endp
409
endp
427
 
410
 
428
if 0
411
if 0
429
 
412
 
430
struc TIMER
413
struc TIMER
431
{
414
{
432
  .next      dd ?
415
  .next      dd ?
433
  .exp_time  dd ?
416
  .exp_time  dd ?
434
  .func      dd ?
417
  .func      dd ?
435
  .arg       dd ?
418
  .arg       dd ?
436
}
419
}
437
 
420
 
438
 
421
 
439
uglobal
422
uglobal
440
rdy_head   rd 16
423
rdy_head   rd 16
441
endg
424
endg
442
 
425
 
443
align 4
426
align 4
444
pick_task:
427
pick_task:
445
 
428
 
446
        xor     eax, eax
429
        xor     eax, eax
447
  .pick:
430
  .pick:
448
        mov     ebx, [rdy_head+eax*4]
431
        mov     ebx, [rdy_head+eax*4]
449
        test    ebx, ebx
432
        test    ebx, ebx
450
        jz      .next
433
        jz      .next
451
 
434
 
452
        mov     [next_task], ebx
435
        mov     [next_task], ebx
453
        test    [ebx+flags.billable]
436
        test    [ebx+flags.billable]
454
        jz      @F
437
        jz      @F
455
        mov     [bill_task], ebx
438
        mov     [bill_task], ebx
456
  @@:
439
  @@:
457
        ret
440
        ret
458
  .next:
441
  .next:
459
        inc     eax
442
        inc     eax
460
        jmp     .pick
443
        jmp     .pick
461
 
444
 
462
; param
445
; param
463
;  eax= task
446
;  eax= task
464
;
447
;
465
; retval
448
; retval
466
;  eax= task
449
;  eax= task
467
;  ebx= queue
450
;  ebx= queue
468
;  ecx= front if 1 or back if 0
451
;  ecx= front if 1 or back if 0
469
align 4
452
align 4
470
shed:
453
shed:
471
        cmp     [eax+.tics_left], 0;signed compare
454
        cmp     [eax+.tics_left], 0;signed compare
472
        mov     ebx, [eax+.priority]
455
        mov     ebx, [eax+.priority]
473
        setg    ecx
456
        setg    ecx
474
        jg      @F
457
        jg      @F
475
 
458
 
476
        mov     edx, [eax+.tics_quantum]
459
        mov     edx, [eax+.tics_quantum]
477
        mov     [eax+.ticks_left], edx
460
        mov     [eax+.ticks_left], edx
478
        cmp     ebx, (IDLE_PRIORITY-1)
461
        cmp     ebx, (IDLE_PRIORITY-1)
479
        je      @F
462
        je      @F
480
        inc     ebx
463
        inc     ebx
481
  @@:
464
  @@:
482
        ret
465
        ret
483
 
466
 
484
; param
467
; param
485
;  eax= task
468
;  eax= task
486
align 4
469
align 4
487
enqueue:
470
enqueue:
488
        call    shed;eax
471
        call    shed;eax
489
        cmp     [rdy_head+ebx*4], 0
472
        cmp     [rdy_head+ebx*4], 0
490
        jnz     @F
473
        jnz     @F
491
 
474
 
492
        mov     [rdy_head+ebx*4], eax
475
        mov     [rdy_head+ebx*4], eax
493
        mov     [rdy_tail+ebx*4], eax
476
        mov     [rdy_tail+ebx*4], eax
494
        mov     [eax+.next_ready], 0
477
        mov     [eax+.next_ready], 0
495
        jmp     .pick
478
        jmp     .pick
496
  @@:
479
  @@:
497
        test    ecx, ecx
480
        test    ecx, ecx
498
        jz      .back
481
        jz      .back
499
 
482
 
500
        mov     ecx, [rdy_head+ebx*4]
483
        mov     ecx, [rdy_head+ebx*4]
501
        mov     [eax+.next_ready], ecx
484
        mov     [eax+.next_ready], ecx
502
        mov     [rdy_head+ebx*4], eax
485
        mov     [rdy_head+ebx*4], eax
503
        jmp     .pick
486
        jmp     .pick
504
  .back:
487
  .back:
505
        mov     ecx, [rdy_tail+ebx*4]
488
        mov     ecx, [rdy_tail+ebx*4]
506
        mov     [ecx+.next_ready], eax
489
        mov     [ecx+.next_ready], eax
507
        mov     [rdy_tail+ebx*4], eax
490
        mov     [rdy_tail+ebx*4], eax
508
        mov     [eax+.next_ready], 0
491
        mov     [eax+.next_ready], 0
509
  .pick:
492
  .pick:
510
        call    pick_proc;select next task
493
        call    pick_proc;select next task
511
        ret
494
        ret
512
 
495
 
513
end if
496
end if