Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
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: 3168 $
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]
3168 art_zh 23
;        call    playNote       ; <<<--- Speaker driver
1055 Galkov 24
        sub     eax,[next_usage_update]
25
        cmp     eax,100
26
        jb      .nocounter
27
        add     [next_usage_update],100
28
        call    updatecputimes
29
  .nocounter:
30
        mov     al,0x20  ; send End Of Interrupt signal
31
        out     0x20,al
32
        btr     dword[DONT_SWITCH], 0
33
        jc      .return
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
46
        call    find_next_task
47
        jz      .return  ; the same task -> skip switch
48
  @@:   mov     byte[DONT_SWITCH], 1
49
        call    do_change_task
50
  .return:
51
        popad
52
        popfd
53
        ret
465 serge 54
 
101 poddubny 55
uglobal
1055 Galkov 56
align 4
57
;  far_jump:
58
;   .offs dd ?
59
;   .sel  dw ?
60
   context_counter     dd 0 ;noname & halyavin
61
   next_usage_update   dd 0
62
   timer_ticks         dd 0
63
;  prev_slot           dd ?
64
;  event_sched         dd ?
101 poddubny 65
endg
66
 
1055 Galkov 67
align 4
101 poddubny 68
update_counters:
1055 Galkov 69
        mov     edi, [TASK_BASE]
70
        rdtsc
71
        sub     eax, [edi+TASKDATA.counter_add] ; time stamp counter add
72
        add     [edi+TASKDATA.counter_sum], eax ; counter sum
73
        ret
74
align 4
75
updatecputimes:
76
        xor     eax,eax
77
        xchg    eax,[idleuse]
78
        mov     [idleusesec],eax
79
        mov     ecx, [TASK_COUNT]
80
        mov     edi, TASK_DATA
81
  .newupdate:
82
        xor     eax,eax
83
        xchg    eax,[edi+TASKDATA.counter_sum]
84
        mov     [edi+TASKDATA.cpu_usage],eax
85
        add     edi,0x20
86
        loop    .newupdate
87
        ret
1 ha 88
 
1055 Galkov 89
align 4
101 poddubny 90
find_next_task:
1055 Galkov 91
;info:
92
;   Find next task to execute
93
;retval:
94
;   ebx = address of the APPDATA for the selected task (slot-base)
95
;   esi = previous slot-base ([current_slot] at the begin)
96
;   edi = address of the TASKDATA for the selected task
97
;   ZF  = 1  if the task is the same
98
;warning:
99
;   [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
100
;   [current_slot] is not set to new value (ebx)!!!
101
;scratched: eax,ecx
102
        call    update_counters ; edi := [TASK_BASE]
103
        Mov     esi, ebx, [current_slot]
104
  .loop:
105
        cmp     bh,[TASK_COUNT]
106
        jb      @f
107
        xor     bh, bh
108
        mov     edi,CURRENT_TASK
109
  @@:   inc     bh       ; ebx += APPDATA.size
110
        add     edi,0x20 ; edi += TASKDATA.size
111
        mov     al, [edi+TASKDATA.state]
112
        test    al, al
113
        jz      .found   ; state == 0
114
        cmp     al, 5
115
        jne     .loop    ; state == 1,2,3,4,9
116
      ; state == 5
117
        pushad  ; more freedom for [APPDATA.wait_test]
118
        call    [ebx+APPDATA.wait_test]
119
        mov     [esp+28],eax
120
        popad
121
        or      eax,eax
122
        jnz     @f
123
      ; testing for timeout
124
        mov     ecx, [timer_ticks]
125
        sub     ecx, [ebx+APPDATA.wait_begin]
126
        cmp     ecx, [ebx+APPDATA.wait_timeout]
127
        jb      .loop
128
  @@:   mov     [ebx+APPDATA.wait_param], eax  ; retval for wait
129
        mov     [edi+TASKDATA.state], 0
130
  .found:
131
        mov     [CURRENT_TASK],bh
132
        mov     [TASK_BASE],edi
133
        rdtsc   ;call  _rdtsc
134
        mov     [edi+TASKDATA.counter_add],eax ; for next using update_counters
135
        cmp     ebx, esi ;esi - previous slot-base
136
        ret
137
;TODO: Надо бы убрать использование do_change_task из V86...
138
; и после этого перенести обработку TASKDATA.counter_add/sum в do_change_task
1 ha 139
 
1055 Galkov 140
align 4
101 poddubny 141
do_change_task:
1055 Galkov 142
;param:
143
;   ebx = address of the APPDATA for incoming task (new)
144
;warning:
145
;   [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task)
146
;   [current_slot] is the outcoming (old), and set here to a new value (ebx)
147
;scratched: eax,ecx,esi
148
        mov     esi,ebx
149
        xchg    esi,[current_slot]
1220 serge 150
; set new stack after saving old
1055 Galkov 151
        mov     [esi+APPDATA.saved_esp], esp
152
        mov     esp, [ebx+APPDATA.saved_esp]
1220 serge 153
; set new thread io-map
1055 Galkov 154
        Mov     dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map]
155
        Mov     dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4]
1220 serge 156
; set new thread memory-map
1055 Galkov 157
        mov     ecx, APPDATA.dir_table
158
        mov     eax, [ebx+ecx]      ;offset>0x7F
159
        cmp     eax, [esi+ecx]      ;offset>0x7F
160
        je      @f
161
        mov     cr3, eax
1220 serge 162
@@:
163
; set tss.esp0
164
 
1055 Galkov 165
        Mov     [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
1220 serge 166
 
167
        mov edx, [ebx+APPDATA.tls_base]
168
        cmp edx, [esi+APPDATA.tls_base]
169
        je @f
170
 
171
        mov     [tls_data_l+2],dx
172
        shr     edx,16
173
        mov     [tls_data_l+4],dl
174
        mov     [tls_data_l+7],dh
175
 
176
        mov dx, app_tls
177
        mov fs, dx
1298 diamond 178
@@:
1220 serge 179
; set gs selector unconditionally
1055 Galkov 180
        Mov     gs,ax,graph_data
181
      ; set CR0.TS
182
        cmp     bh, byte[fpu_owner] ;bh == incoming task (new)
183
        clts                        ;clear a task switch flag
184
        je      @f
185
        mov     eax, cr0            ;and set it again if the owner
186
        or      eax, CR0_TS         ;of a fpu has changed
187
        mov     cr0, eax
188
  @@: ; set context_counter (only for user pleasure ???)
189
        inc     [context_counter]   ;noname & halyavin
190
      ; set debug-registers, if it's necessary
191
        test    byte[ebx+APPDATA.dbg_state], 1
192
        jz      @f
193
        xor     eax, eax
194
        mov     dr6, eax
195
        lea     esi,[ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table] ;offset>0x7F
196
        cld
197
  macro lodsReg [reg] {
198
        lodsd
199
        mov     reg,eax
200
  }     lodsReg dr0, dr1, dr2, dr3, dr7
201
  purge lodsReg
202
  @@:   ret
203
;end.
465 serge 204
 
1434 serge 205
 
206
 
207
struc MUTEX_WAITER
208
{
209
    .next   rd 1
210
    .prev   rd 1
211
    .task   rd 1
212
    .sizeof:
213
};
214
 
215
virtual at 0
216
 MUTEX_WAITER MUTEX_WAITER
217
end virtual
218
 
219
;void  __fastcall mutex_init(struct mutex *lock)
220
 
221
align 4
222
mutex_init:
223
        lea eax, [ecx+MUTEX.next]
224
        mov [ecx+MUTEX.count],1
225
        mov [ecx+MUTEX.next], eax
226
        mov [ecx+MUTEX.prev], eax
227
        ret
228
 
229
 
230
;void  __fastcall mutex_lock(struct mutex *lock)
231
 
232
align 4
233
mutex_lock:
234
 
235
        dec [ecx+MUTEX.count]
236
        jns .done
237
 
238
        pushfd
239
        cli
240
 
241
        push esi
242
        sub esp, MUTEX_WAITER.sizeof
243
 
244
        mov eax, [ecx+MUTEX.prev]
245
        lea esi, [ecx+MUTEX.next]
246
 
247
        mov [ecx+MUTEX.prev], esp
248
        mov [esp+MUTEX_WAITER.next],  esi
249
        mov [esp+MUTEX_WAITER.prev],  eax
250
        mov [eax], esp
251
 
252
        mov edx, [TASK_BASE]
253
        mov [esp+MUTEX_WAITER.task], edx
254
 
255
.forever:
256
 
257
        mov eax, -1
258
        xchg eax, [ecx+MUTEX.count]
259
        dec eax
260
        jz @F
261
 
262
        mov [edx+TASKDATA.state], 1
263
        call change_task
264
        jmp .forever
265
@@:
266
        mov edx, [esp+MUTEX_WAITER.next]
267
        mov eax, [esp+MUTEX_WAITER.prev]
268
 
269
        mov [eax+MUTEX_WAITER.next], edx
270
        cmp [ecx+MUTEX.next], esi
271
        mov [edx+MUTEX_WAITER.prev], eax
272
        jne @F
273
 
274
        mov [ecx+MUTEX.count], 0
275
@@:
276
        add  esp, MUTEX_WAITER.sizeof
277
 
278
        pop esi
279
        popfd
280
.done:
281
        ret
282
 
283
;void  __fastcall mutex_unlock(struct mutex *lock)
284
 
285
align 4
286
mutex_unlock:
287
 
288
        pushfd
289
        cli
290
 
291
        lea eax, [ecx+MUTEX.next]
292
        cmp eax, [ecx+MUTEX.next]
293
        mov [ecx+MUTEX.count], 1
294
        je @F
295
 
296
        mov eax, [eax+MUTEX_WAITER.task]
297
        mov [eax+TASKDATA.state], 0
298
@@:
299
        popfd
300
        ret
301
 
302
 
303
purge MUTEX_WAITER
304
 
465 serge 305
if 0
1434 serge 306
 
465 serge 307
struc TIMER
308
{
309
  .next      dd ?
310
  .exp_time  dd ?
311
  .func      dd ?
1055 Galkov 312
  .arg       dd ?
465 serge 313
}
314
 
1276 Lrz 315
 
1055 Galkov 316
MAX_PROIRITY         0   ; highest, used for kernel tasks
317
MAX_USER_PRIORITY    0   ; highest priority for user processes
318
USER_PRIORITY        7   ; default (should correspond to nice 0)
319
MIN_USER_PRIORITY   14   ; minimum priority for user processes
320
IDLE_PRIORITY       15   ; lowest, only IDLE process goes here
321
NR_SCHED_QUEUES     16   ; MUST equal IDLE_PRIORYTY + 1
465 serge 322
 
1276 Lrz 323
uglobal
465 serge 324
rdy_head   rd 16
1276 Lrz 325
endg
465 serge 326
 
327
align 4
328
pick_task:
329
 
1055 Galkov 330
       xor eax, eax
331
  .pick:
332
       mov ebx, [rdy_head+eax*4]
333
       test ebx, ebx
334
       jz .next
465 serge 335
 
1055 Galkov 336
       mov [next_task], ebx
337
       test [ebx+flags.billable]
338
       jz @F
339
       mov [bill_task], ebx
340
  @@:
341
       ret
342
  .next:
343
       inc eax
344
       jmp .pick
465 serge 345
 
346
; param
347
;  eax= task
348
;
349
; retval
350
;  eax= task
351
;  ebx= queue
352
;  ecx= front if 1 or back if 0
353
align 4
354
shed:
1055 Galkov 355
       cmp [eax+.tics_left], 0 ;signed compare
356
       mov ebx, [eax+.priority]
357
       setg ecx
358
       jg @F
465 serge 359
 
1055 Galkov 360
       mov edx, [eax+.tics_quantum]
361
       mov [eax+.ticks_left], edx
362
       cmp ebx, (IDLE_PRIORITY-1)
363
       je @F
364
       inc ebx
365
  @@:
366
       ret
465 serge 367
 
368
; param
369
;  eax= task
370
align 4
371
enqueue:
1055 Galkov 372
      call shed  ;eax
373
      cmp [rdy_head+ebx*4],0
374
      jnz @F
465 serge 375
 
1055 Galkov 376
      mov [rdy_head+ebx*4], eax
377
      mov [rdy_tail+ebx*4], eax
378
      mov [eax+.next_ready], 0
379
      jmp .pick
380
  @@:
381
      test ecx, ecx
382
      jz .back
465 serge 383
 
1055 Galkov 384
      mov ecx, [rdy_head+ebx*4]
385
      mov [eax+.next_ready], ecx
386
      mov [rdy_head+ebx*4], eax
387
      jmp .pick
388
  .back:
389
      mov ecx, [rdy_tail+ebx*4]
390
      mov [ecx+.next_ready], eax
391
      mov [rdy_tail+ebx*4], eax
392
      mov [eax+.next_ready], 0
393
  .pick:
394
      call pick_proc     ;select next task
395
      ret
465 serge 396
 
397
end if