Subversion Repositories Kolibri OS

Rev

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

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