Subversion Repositories Kolibri OS

Rev

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

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