Subversion Repositories Kolibri OS

Rev

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

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