Subversion Repositories Kolibri OS

Rev

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