Subversion Repositories Kolibri OS

Rev

Rev 9600 | Rev 9709 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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