413 lines
10 KiB
PHP
413 lines
10 KiB
PHP
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||
|
;; ;;
|
|||
|
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
|||
|
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
|||
|
;; Distributed under terms of the GNU General Public License ;;
|
|||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||
|
|
|||
|
$Revision$
|
|||
|
|
|||
|
|
|||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||
|
;; IRQ0 HANDLER (TIMER INTERRUPT) ;;
|
|||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|||
|
|
|||
|
|
|||
|
align 32
|
|||
|
irq0:
|
|||
|
pushad
|
|||
|
Mov ds, ax, app_data
|
|||
|
mov es, ax
|
|||
|
inc [timer_ticks]
|
|||
|
mov eax, [timer_ticks]
|
|||
|
call playNote ; <<<--- Speaker driver
|
|||
|
sub eax,[next_usage_update]
|
|||
|
cmp eax,100
|
|||
|
jb .nocounter
|
|||
|
add [next_usage_update],100
|
|||
|
call updatecputimes
|
|||
|
.nocounter:
|
|||
|
mov al,0x20 ; send End Of Interrupt signal
|
|||
|
out 0x20,al
|
|||
|
btr dword[DONT_SWITCH], 0
|
|||
|
jc .return
|
|||
|
call find_next_task
|
|||
|
jz .return ; if there is only one running process
|
|||
|
call do_change_task
|
|||
|
.return:
|
|||
|
popad
|
|||
|
iretd
|
|||
|
|
|||
|
align 4
|
|||
|
change_task:
|
|||
|
pushfd
|
|||
|
cli
|
|||
|
pushad
|
|||
|
if 0
|
|||
|
; \begin{Mario79} ; <- must be refractoried, if used...
|
|||
|
cmp [dma_task_switched], 1
|
|||
|
jne .find_next_task
|
|||
|
mov [dma_task_switched], 0
|
|||
|
mov ebx, [dma_process]
|
|||
|
cmp [CURRENT_TASK], ebx
|
|||
|
je .return
|
|||
|
mov edi, [dma_slot_ptr]
|
|||
|
mov [CURRENT_TASK], ebx
|
|||
|
mov [TASK_BASE], edi
|
|||
|
jmp @f
|
|||
|
.find_next_task:
|
|||
|
; \end{Mario79}
|
|||
|
end if
|
|||
|
call find_next_task
|
|||
|
jz .return ; the same task -> skip switch
|
|||
|
@@: mov byte[DONT_SWITCH], 1
|
|||
|
call do_change_task
|
|||
|
.return:
|
|||
|
popad
|
|||
|
popfd
|
|||
|
ret
|
|||
|
|
|||
|
uglobal
|
|||
|
align 4
|
|||
|
; far_jump:
|
|||
|
; .offs dd ?
|
|||
|
; .sel dw ?
|
|||
|
context_counter dd 0 ;noname & halyavin
|
|||
|
next_usage_update dd 0
|
|||
|
timer_ticks dd 0
|
|||
|
; prev_slot dd ?
|
|||
|
; event_sched dd ?
|
|||
|
endg
|
|||
|
|
|||
|
align 4
|
|||
|
update_counters:
|
|||
|
mov edi, [TASK_BASE]
|
|||
|
rdtsc
|
|||
|
sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add
|
|||
|
add [edi+TASKDATA.counter_sum], eax ; counter sum
|
|||
|
ret
|
|||
|
align 4
|
|||
|
updatecputimes:
|
|||
|
xor eax,eax
|
|||
|
xchg eax,[idleuse]
|
|||
|
mov [idleusesec],eax
|
|||
|
mov ecx, [TASK_COUNT]
|
|||
|
mov edi, TASK_DATA
|
|||
|
.newupdate:
|
|||
|
xor eax,eax
|
|||
|
xchg eax,[edi+TASKDATA.counter_sum]
|
|||
|
mov [edi+TASKDATA.cpu_usage],eax
|
|||
|
add edi,0x20
|
|||
|
loop .newupdate
|
|||
|
ret
|
|||
|
|
|||
|
align 4
|
|||
|
find_next_task:
|
|||
|
;info:
|
|||
|
; Find next task to execute
|
|||
|
;retval:
|
|||
|
; ebx = address of the APPDATA for the selected task (slot-base)
|
|||
|
; esi = previous slot-base ([current_slot] at the begin)
|
|||
|
; edi = address of the TASKDATA for the selected task
|
|||
|
; ZF = 1 if the task is the same
|
|||
|
;warning:
|
|||
|
; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result
|
|||
|
; [current_slot] is not set to new value (ebx)!!!
|
|||
|
;scratched: eax,ecx
|
|||
|
call update_counters ; edi := [TASK_BASE]
|
|||
|
Mov esi, ebx, [current_slot]
|
|||
|
.loop:
|
|||
|
cmp bh,[TASK_COUNT]
|
|||
|
jb @f
|
|||
|
xor bh, bh
|
|||
|
mov edi,CURRENT_TASK
|
|||
|
@@: inc bh ; ebx += APPDATA.size
|
|||
|
add edi,0x20 ; edi += TASKDATA.size
|
|||
|
mov al, [edi+TASKDATA.state]
|
|||
|
test al, al
|
|||
|
jz .found ; state == 0
|
|||
|
cmp al, 5
|
|||
|
jne .loop ; state == 1,2,3,4,9
|
|||
|
; state == 5
|
|||
|
pushad ; more freedom for [APPDATA.wait_test]
|
|||
|
call [ebx+APPDATA.wait_test]
|
|||
|
mov [esp+28],eax
|
|||
|
popad
|
|||
|
or eax,eax
|
|||
|
jnz @f
|
|||
|
; testing for timeout
|
|||
|
mov ecx, [timer_ticks]
|
|||
|
sub ecx, [ebx+APPDATA.wait_begin]
|
|||
|
cmp ecx, [ebx+APPDATA.wait_timeout]
|
|||
|
jb .loop
|
|||
|
@@: mov [ebx+APPDATA.wait_param], eax ; retval for wait
|
|||
|
mov [edi+TASKDATA.state], 0
|
|||
|
.found:
|
|||
|
mov [CURRENT_TASK],bh
|
|||
|
mov [TASK_BASE],edi
|
|||
|
rdtsc ;call _rdtsc
|
|||
|
mov [edi+TASKDATA.counter_add],eax ; for next using update_counters
|
|||
|
cmp ebx, esi ;esi - previous slot-base
|
|||
|
ret
|
|||
|
;TODO: <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> do_change_task <EFBFBD><EFBFBD> V86...
|
|||
|
; <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TASKDATA.counter_add/sum <EFBFBD> do_change_task
|
|||
|
|
|||
|
align 4
|
|||
|
do_change_task:
|
|||
|
;param:
|
|||
|
; ebx = address of the APPDATA for incoming task (new)
|
|||
|
;warning:
|
|||
|
; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task)
|
|||
|
; [current_slot] is the outcoming (old), and set here to a new value (ebx)
|
|||
|
;scratched: eax,ecx,esi
|
|||
|
mov esi,ebx
|
|||
|
xchg esi,[current_slot]
|
|||
|
; set new stack after saving old
|
|||
|
mov [esi+APPDATA.saved_esp], esp
|
|||
|
mov esp, [ebx+APPDATA.saved_esp]
|
|||
|
; set new thread io-map
|
|||
|
Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map]
|
|||
|
Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4]
|
|||
|
; set new thread memory-map
|
|||
|
mov ecx, APPDATA.dir_table
|
|||
|
mov eax, [ebx+ecx] ;offset>0x7F
|
|||
|
cmp eax, [esi+ecx] ;offset>0x7F
|
|||
|
je @f
|
|||
|
mov cr3, eax
|
|||
|
@@:
|
|||
|
; set tss.esp0
|
|||
|
|
|||
|
Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0]
|
|||
|
|
|||
|
mov edx, [ebx+APPDATA.tls_base]
|
|||
|
cmp edx, [esi+APPDATA.tls_base]
|
|||
|
je @f
|
|||
|
|
|||
|
mov [tls_data_l+2],dx
|
|||
|
shr edx,16
|
|||
|
mov [tls_data_l+4],dl
|
|||
|
mov [tls_data_l+7],dh
|
|||
|
|
|||
|
mov dx, app_tls
|
|||
|
mov fs, dx
|
|||
|
@@:
|
|||
|
; set gs selector unconditionally
|
|||
|
Mov gs,ax,graph_data
|
|||
|
; set CR0.TS
|
|||
|
cmp bh, byte[fpu_owner] ;bh == incoming task (new)
|
|||
|
clts ;clear a task switch flag
|
|||
|
je @f
|
|||
|
mov eax, cr0 ;and set it again if the owner
|
|||
|
or eax, CR0_TS ;of a fpu has changed
|
|||
|
mov cr0, eax
|
|||
|
@@: ; set context_counter (only for user pleasure ???)
|
|||
|
inc [context_counter] ;noname & halyavin
|
|||
|
; set debug-registers, if it's necessary
|
|||
|
test byte[ebx+APPDATA.dbg_state], 1
|
|||
|
jz @f
|
|||
|
xor eax, eax
|
|||
|
mov dr6, eax
|
|||
|
lea esi,[ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table] ;offset>0x7F
|
|||
|
cld
|
|||
|
macro lodsReg [reg] {
|
|||
|
lodsd
|
|||
|
mov reg,eax
|
|||
|
} lodsReg dr0, dr1, dr2, dr3, dr7
|
|||
|
purge lodsReg
|
|||
|
@@: ret
|
|||
|
;end.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
struc MUTEX_WAITER
|
|||
|
{
|
|||
|
.next rd 1
|
|||
|
.prev rd 1
|
|||
|
.task rd 1
|
|||
|
.sizeof:
|
|||
|
};
|
|||
|
|
|||
|
virtual at 0
|
|||
|
MUTEX_WAITER MUTEX_WAITER
|
|||
|
end virtual
|
|||
|
|
|||
|
;void __fastcall mutex_init(struct mutex *lock)
|
|||
|
|
|||
|
align 4
|
|||
|
mutex_init:
|
|||
|
lea eax, [ecx+MUTEX.next]
|
|||
|
mov [ecx+MUTEX.count],1
|
|||
|
mov [ecx+MUTEX.next], eax
|
|||
|
mov [ecx+MUTEX.prev], eax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;void __fastcall mutex_lock(struct mutex *lock)
|
|||
|
|
|||
|
align 4
|
|||
|
mutex_lock:
|
|||
|
|
|||
|
dec [ecx+MUTEX.count]
|
|||
|
jns .done
|
|||
|
|
|||
|
pushfd
|
|||
|
cli
|
|||
|
|
|||
|
push esi
|
|||
|
sub esp, MUTEX_WAITER.sizeof
|
|||
|
|
|||
|
mov eax, [ecx+MUTEX.prev]
|
|||
|
lea esi, [ecx+MUTEX.next]
|
|||
|
|
|||
|
mov [ecx+MUTEX.prev], esp
|
|||
|
mov [esp+MUTEX_WAITER.next], esi
|
|||
|
mov [esp+MUTEX_WAITER.prev], eax
|
|||
|
mov [eax], esp
|
|||
|
|
|||
|
mov edx, [TASK_BASE]
|
|||
|
mov [esp+MUTEX_WAITER.task], edx
|
|||
|
|
|||
|
.forever:
|
|||
|
|
|||
|
mov eax, -1
|
|||
|
xchg eax, [ecx+MUTEX.count]
|
|||
|
dec eax
|
|||
|
jz @F
|
|||
|
|
|||
|
mov [edx+TASKDATA.state], 1
|
|||
|
call change_task
|
|||
|
jmp .forever
|
|||
|
@@:
|
|||
|
mov edx, [esp+MUTEX_WAITER.next]
|
|||
|
mov eax, [esp+MUTEX_WAITER.prev]
|
|||
|
|
|||
|
mov [eax+MUTEX_WAITER.next], edx
|
|||
|
cmp [ecx+MUTEX.next], esi
|
|||
|
mov [edx+MUTEX_WAITER.prev], eax
|
|||
|
jne @F
|
|||
|
|
|||
|
mov [ecx+MUTEX.count], 0
|
|||
|
@@:
|
|||
|
add esp, MUTEX_WAITER.sizeof
|
|||
|
|
|||
|
pop esi
|
|||
|
popfd
|
|||
|
.done:
|
|||
|
ret
|
|||
|
|
|||
|
;void __fastcall mutex_unlock(struct mutex *lock)
|
|||
|
|
|||
|
align 4
|
|||
|
mutex_unlock:
|
|||
|
|
|||
|
pushfd
|
|||
|
cli
|
|||
|
|
|||
|
lea eax, [ecx+MUTEX.next]
|
|||
|
cmp eax, [ecx+MUTEX.next]
|
|||
|
mov [ecx+MUTEX.count], 1
|
|||
|
je @F
|
|||
|
|
|||
|
mov eax, [eax+MUTEX_WAITER.task]
|
|||
|
mov [eax+TASKDATA.state], 0
|
|||
|
@@:
|
|||
|
popfd
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
purge MUTEX_WAITER
|
|||
|
|
|||
|
if 0
|
|||
|
|
|||
|
struc TIMER
|
|||
|
{
|
|||
|
.next dd ?
|
|||
|
.exp_time dd ?
|
|||
|
.func dd ?
|
|||
|
.arg dd ?
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
MAX_PROIRITY 0 ; highest, used for kernel tasks
|
|||
|
MAX_USER_PRIORITY 0 ; highest priority for user processes
|
|||
|
USER_PRIORITY 7 ; default (should correspond to nice 0)
|
|||
|
MIN_USER_PRIORITY 14 ; minimum priority for user processes
|
|||
|
IDLE_PRIORITY 15 ; lowest, only IDLE process goes here
|
|||
|
NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1
|
|||
|
|
|||
|
uglobal
|
|||
|
rdy_head rd 16
|
|||
|
endg
|
|||
|
|
|||
|
align 4
|
|||
|
pick_task:
|
|||
|
|
|||
|
xor eax, eax
|
|||
|
.pick:
|
|||
|
mov ebx, [rdy_head+eax*4]
|
|||
|
test ebx, ebx
|
|||
|
jz .next
|
|||
|
|
|||
|
mov [next_task], ebx
|
|||
|
test [ebx+flags.billable]
|
|||
|
jz @F
|
|||
|
mov [bill_task], ebx
|
|||
|
@@:
|
|||
|
ret
|
|||
|
.next:
|
|||
|
inc eax
|
|||
|
jmp .pick
|
|||
|
|
|||
|
; param
|
|||
|
; eax= task
|
|||
|
;
|
|||
|
; retval
|
|||
|
; eax= task
|
|||
|
; ebx= queue
|
|||
|
; ecx= front if 1 or back if 0
|
|||
|
align 4
|
|||
|
shed:
|
|||
|
cmp [eax+.tics_left], 0 ;signed compare
|
|||
|
mov ebx, [eax+.priority]
|
|||
|
setg ecx
|
|||
|
jg @F
|
|||
|
|
|||
|
mov edx, [eax+.tics_quantum]
|
|||
|
mov [eax+.ticks_left], edx
|
|||
|
cmp ebx, (IDLE_PRIORITY-1)
|
|||
|
je @F
|
|||
|
inc ebx
|
|||
|
@@:
|
|||
|
ret
|
|||
|
|
|||
|
; param
|
|||
|
; eax= task
|
|||
|
align 4
|
|||
|
enqueue:
|
|||
|
call shed ;eax
|
|||
|
cmp [rdy_head+ebx*4],0
|
|||
|
jnz @F
|
|||
|
|
|||
|
mov [rdy_head+ebx*4], eax
|
|||
|
mov [rdy_tail+ebx*4], eax
|
|||
|
mov [eax+.next_ready], 0
|
|||
|
jmp .pick
|
|||
|
@@:
|
|||
|
test ecx, ecx
|
|||
|
jz .back
|
|||
|
|
|||
|
mov ecx, [rdy_head+ebx*4]
|
|||
|
mov [eax+.next_ready], ecx
|
|||
|
mov [rdy_head+ebx*4], eax
|
|||
|
jmp .pick
|
|||
|
.back:
|
|||
|
mov ecx, [rdy_tail+ebx*4]
|
|||
|
mov [ecx+.next_ready], eax
|
|||
|
mov [rdy_tail+ebx*4], eax
|
|||
|
mov [eax+.next_ready], 0
|
|||
|
.pick:
|
|||
|
call pick_proc ;select next task
|
|||
|
ret
|
|||
|
|
|||
|
end if
|