Subversion Repositories Kolibri OS

Rev

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