Subversion Repositories Kolibri OS

Rev

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

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