Subversion Repositories Kolibri OS

Rev

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

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