/kernel/branches/Kolibri-acpi/core/apic.inc |
---|
5,7 → 5,7 |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
IRQ_RESERVE = 24 ; 16 or 24 |
IRQ_RESERVED = 24 ; 16 or 24 |
iglobal |
IRQ_COUNT dd 24 |
62,10 → 62,11 |
shr eax, 16 |
inc al |
movzx eax, al |
cmp al, IRQ_RESERVE |
cmp al, IRQ_RESERVED |
jbe @f |
mov al, IRQ_RESERVE |
@@: mov [IRQ_COUNT], eax |
mov al, IRQ_RESERVED |
@@: |
mov [IRQ_COUNT], eax |
; Reroute IOAPIC & mask all interrupts |
xor ecx, ecx |
106,7 → 107,7 |
;init handlers table |
mov ecx, IRQ_RESERVE |
mov ecx, IRQ_RESERVED |
mov edi, irqh_tab |
@@: |
mov eax, edi |
/kernel/branches/Kolibri-acpi/core/exports.inc |
---|
85,7 → 85,14 |
szStrchr db 'strchr',0 |
szStrrchr db 'strrchr',0 |
szDiskAdd db 'DiskAdd',0 |
szDiskDel db 'DiskDel',0 |
szDiskMediaChanged db 'DiskMediaChanged',0 |
szTimerHS db 'TimerHS',0 |
szCancelTimerHS db 'CancelTimerHS',0 |
align 16 |
kernel_export: |
dd szRegService , reg_service |
/kernel/branches/Kolibri-acpi/core/heap.inc |
---|
151,7 → 151,8 |
mov [mem_block_list+63*4], ebx |
mov byte [mem_block_map], 0xFC |
and [heap_mutex], 0 |
mov ecx, heap_mutex |
call mutex_init |
mov [heap_blocks], 4095 |
mov [free_blocks], 4094 |
ret |
272,14 → 273,14 |
push esi |
push edi |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095 |
mov [size], eax |
mov ebx, heap_mutex |
call wait_mutex ;ebx |
cmp eax, [heap_free] |
ja .error |
355,10 → 356,11 |
mov [edx+list_bk], esi |
mov [esi+block_flags], USED_BLOCK |
mov eax, [esi+block_base] |
mov ebx, [size] |
sub [heap_free], ebx |
and [heap_mutex], 0 |
mov ecx, heap_mutex |
call mutex_unlock |
mov eax, [esi+block_base] |
pop edi |
pop esi |
pop ebx |
378,17 → 380,19 |
mov [edx+list_bk], edi |
mov [edi+block_flags], USED_BLOCK |
mov eax, [edi+block_base] |
mov ebx, [size] |
sub [heap_free], ebx |
and [heap_mutex], 0 |
mov ecx, heap_mutex |
call mutex_unlock |
mov eax, [edi+block_base] |
pop edi |
pop esi |
pop ebx |
ret |
.error: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
mov [heap_mutex], eax |
pop edi |
pop esi |
pop ebx |
400,9 → 404,10 |
push ebx |
push esi |
push edi |
mov ebx, heap_mutex |
call wait_mutex ;ebx |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [base] |
mov esi, [mem_used.fd] |
@@: |
491,9 → 496,10 |
@@: |
bts [mem_block_mask], eax |
.m_eq: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
mov [heap_mutex], eax |
dec eax |
not eax |
pop edi |
pop esi |
pop ebx |
513,16 → 519,18 |
@@: |
bts [mem_block_mask], eax |
mov [esi+block_flags],FREE_BLOCK |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
mov [heap_mutex], eax |
dec eax |
not eax |
pop edi |
pop esi |
pop ebx |
ret |
.fail: |
mov ecx, heap_mutex |
call mutex_unlock |
xor eax, eax |
mov [heap_mutex], eax |
pop edi |
pop esi |
pop ebx |
607,8 → 615,8 |
proc kernel_free stdcall, base:dword |
push ebx esi |
mov ebx, heap_mutex |
call wait_mutex ;ebx |
mov ecx, heap_mutex |
call mutex_lock |
mov eax, [base] |
mov esi, [mem_used.fd] |
624,19 → 632,17 |
cmp [esi+block_flags], USED_BLOCK |
jne .fail |
and [heap_mutex], 0 |
call mutex_unlock |
push ecx |
mov ecx, [esi+block_size]; |
shr ecx, 12 |
call release_pages ;eax, ecx |
pop ecx |
stdcall free_kernel_space, [base] |
pop esi ebx |
ret |
.fail: |
call mutex_unlock |
xor eax, eax |
mov [heap_mutex], eax |
pop esi ebx |
ret |
endp |
/kernel/branches/Kolibri-acpi/core/irq.inc |
---|
5,6 → 5,10 |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
IRQ_POOL_SIZE equ 48 |
macro __list_add new, prev, next |
{ |
mov [next+LHEAD.prev], new |
28,13 → 32,13 |
uglobal |
align 16 |
irqh_tab rd LHEAD.sizeof * IRQ_RESERVE / 4 |
irqh_tab rd LHEAD.sizeof * IRQ_RESERVED / 4 |
irqh_pool rd IRQH.sizeof *48 /4 |
irqh_pool rd IRQH.sizeof * IRQ_POOL_SIZE /4 |
next_irqh rd 1 |
irq_active_set rd 1 |
irq_failed rd IRQ_RESERVE |
irq_failed rd IRQ_RESERVED |
endg |
44,8 → 48,6 |
.irqh dd ? |
endl |
xchg bx, bx |
and [.irqh], 0 |
push ebx |
54,7 → 56,7 |
test ebx, ebx |
jz .err |
cmp ebx, IRQ_RESERVE |
cmp ebx, IRQ_RESERVED |
jae .err |
mov edx, [handler] |
72,9 → 74,10 |
mov eax, [ecx] |
mov [next_irqh], eax |
mov [.irqh], ecx |
mov [irq_failed+ebx*4], 0 ;clear counter |
mov eax, [user_data] |
mov [ecx+IRQH.handler], edx |
mov [ecx+IRQH.data], eax |
81,9 → 84,8 |
lea edx, [irqh_tab+ebx*8] |
list_add_tail ecx, edx ;clobber eax |
stdcall enable_irq, ebx |
stdcall enable_irq, [irq] |
.fail: |
popfd |
.err: |
116,7 → 118,6 |
endp |
macro irq_serv_h [num] { |
forward |
align 4 |
142,8 → 143,6 |
.main: |
save_ring3_context |
xchg bx, bx |
mov ebp, [esp + 32] |
mov bx, app_data ;os_data |
mov ds, bx |
212,4 → 211,15 |
add esp, 4 |
iret |
align 4 |
irqD: |
push eax |
push ecx |
xor eax,eax |
out 0xf0,al |
mov eax, 13 |
call IRQ_EOI |
pop ecx |
pop eax |
iret |
/kernel/branches/Kolibri-acpi/core/malloc.inc |
---|
20,7 → 20,7 |
; esi= nb |
; ebx= idx |
; |
align 16 |
align 4 |
malloc: |
push esi |
31,8 → 31,8 |
and esi, -8 |
add esi, 8 |
mov ebx, mst.mutex |
call wait_mutex ;ebx |
mov ecx, mst.mutex |
call mutex_lock |
cmp esi, 256 |
jae .large |
92,9 → 92,13 |
pop edi |
pop ebp |
.done: |
mov esi, eax |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
mov [mst.mutex], 0 |
ret |
.split: |
lea ebx, [edx+8] ;ebx=mem |
133,10 → 137,10 |
mov [edx+12], eax ; F->bk = r; |
mov [eax+8], edx ; r->fd = F; |
mov [eax+12], ecx ; r->bk = B; |
mov eax, ebx |
pop esi |
mov [mst.mutex], 0 |
ret |
jmp .done |
.small: |
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) |
150,9 → 154,8 |
call malloc_small |
test eax, eax |
jz .from_top |
pop esi |
and [mst.mutex], 0 |
ret |
jmp .done |
.large: |
; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0) |
189,18 → 192,15 |
mov [edx+4], eax |
mov [ecx+4], esi |
lea eax, [ecx+8] |
pop esi |
and [mst.mutex], 0 |
ret |
jmp .done |
.fail: |
xor eax, eax |
pop esi |
and [mst.mutex], 0 |
ret |
jmp .done |
; param |
; eax= mem |
align 4 |
free: |
push edi |
mov edi, eax |
211,8 → 211,8 |
test byte [edi+4], 2 |
je .fail |
mov ebx, mst.mutex |
call wait_mutex ;ebx |
mov ecx, mst.mutex |
call mutex_lock |
; psize = p->head & (~3); |
289,7 → 289,10 |
mov [mst.top], edi |
mov [edi+4], eax |
.fail2: |
and [mst.mutex], 0 |
mov esi, eax |
mov ecx, mst.mutex |
call mutex_unlock |
mov eax, esi |
pop esi |
.fail: |
pop edi |
410,13 → 413,15 |
mov [esi+8], edx ;P->fd = F |
mov [esi+12], eax ;P->bk = B |
pop esi |
and [mst.mutex], 0 |
mov ecx, mst.mutex |
call mutex_unlock |
ret |
.large: |
mov ebx, eax |
call insert_large_chunk |
pop esi |
and [mst.mutex], 0 |
mov ecx, mst.mutex |
call mutex_unlock |
ret |
1025,5 → 1030,8 |
cmp eax, mst.smallbins+512 |
jb @B |
mov ecx, mst.mutex |
call mutex_init |
ret |
/kernel/branches/Kolibri-acpi/core/memory.inc |
---|
214,30 → 214,32 |
align 4 |
commit_pages: |
push edi |
test ecx, ecx |
jz .fail |
push edi |
push eax |
push ecx |
mov ecx, pg_data.mutex |
call mutex_lock |
pop ecx |
pop eax |
mov edi, ebx |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
shr edi, 12 |
lea edi, [page_tabs+edi*4] |
@@: |
stosd |
invlpg [ebx] |
add eax, 0x1000 |
add ebx, 0x1000 |
loop @B |
mov edx, 0x1000 |
mov ebx, edi |
shr ebx, 12 |
@@: |
mov [page_tabs+ebx*4], eax |
; push eax |
invlpg [edi] |
; pop eax |
add edi, edx |
add eax, edx |
inc ebx |
dec ecx |
jnz @B |
mov [pg_data.pg_mutex],ecx |
pop edi |
mov ecx, pg_data.mutex |
call mutex_unlock |
.fail: |
pop edi |
ret |
248,16 → 250,22 |
align 4 |
release_pages: |
pushad |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
push ebp |
push esi |
push edi |
push ebx |
mov esi, eax |
mov edi, eax |
shr esi, 10 |
add esi, page_tabs |
shr esi, 12 |
lea esi, [page_tabs+esi*4] |
push ecx |
mov ecx, pg_data.mutex |
call mutex_lock |
pop ecx |
mov ebp, [pg_data.pages_free] |
mov ebx, [page_start] |
mov edx, sys_pgmap |
264,9 → 272,7 |
@@: |
xor eax, eax |
xchg eax, [esi] |
push eax |
invlpg [edi] |
pop eax |
test eax, 1 |
jz .next |
285,11 → 291,16 |
.next: |
add edi, 0x1000 |
add esi, 4 |
dec ecx |
jnz @B |
loop @B |
mov [pg_data.pages_free], ebp |
and [pg_data.pg_mutex],0 |
popad |
mov ecx, pg_data.mutex |
call mutex_unlock |
pop ebx |
pop edi |
pop esi |
pop ebp |
ret |
; param |
423,8 → 434,8 |
align 4 |
proc new_mem_resize stdcall, new_size:dword |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov ecx, pg_data.mutex |
call mutex_lock |
mov edi, [new_size] |
add edi,4095 |
464,8 → 475,10 |
mov ebx, [new_size] |
call update_mem_size |
mov ecx, pg_data.mutex |
call mutex_unlock |
xor eax, eax |
dec [pg_data.pg_mutex] |
ret |
.expand: |
539,9 → 552,11 |
pop edi |
pop esi |
.exit: |
mov ecx, pg_data.mutex |
call mutex_unlock |
xor eax, eax |
inc eax |
dec [pg_data.pg_mutex] |
ret |
endp |
/kernel/branches/Kolibri-acpi/core/sys32.inc |
---|
54,7 → 54,7 |
dd irq_serv.irq_22 |
dd irq_serv.irq_23 |
times 32 - IRQ_RESERVE dd unknown_interrupt |
times 32 - IRQ_RESERVED dd unknown_interrupt |
;int_0x40 gate trap (for directly copied) |
dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16 |
246,18 → 246,6 |
align 4 |
irqD: |
push eax |
xor eax,eax |
out 0xf0,al |
mov al,0x20 |
out 0xa0,al |
out 0x20,al |
pop eax |
iret |
align 4 |
set_application_table_status: |
push eax |
682,8 → 670,13 |
restore .slot |
iglobal |
if lang eq ru |
boot_sched_1 db '®§¤ ¨¥ GDT TSS 㪠§ ⥫ï',0 |
boot_sched_2 db '®§¤ ¨¥ IDT â ¡«¨æë',0 |
else |
boot_sched_1 db 'Building gdt tss pointer',0 |
boot_sched_2 db 'Building IDT table',0 |
end if |
endg |
/kernel/branches/Kolibri-acpi/core/taskman.inc |
---|
360,8 → 360,8 |
app_tabs dd ? |
endl |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov ecx, pg_data.mutex |
call mutex_lock |
xor eax, eax |
mov [dir_addr], eax |
480,11 → 480,13 |
.done: |
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP |
dec [pg_data.pg_mutex] |
mov ecx, pg_data.mutex |
call mutex_unlock |
mov eax, [dir_addr] |
ret |
.fail: |
dec [pg_data.pg_mutex] |
mov ecx, pg_data.mutex |
call mutex_unlock |
cmp [dir_addr], 0 |
je @f |
stdcall destroy_app_space, [dir_addr], 0 |
554,10 → 556,10 |
jg .ret |
;if there isn't threads then clear memory. |
mov esi, [dlls_list] |
call destroy_all_hdlls |
call destroy_all_hdlls ;ecx=APPDATA |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov ecx, pg_data.mutex |
call mutex_lock |
mov eax, [pg_dir] |
and eax, not 0xFFF |
583,7 → 585,8 |
.exit: |
stdcall map_page,[tmp_task_ptab],0,PG_UNMAP |
stdcall map_page,[tmp_task_pdir],0,PG_UNMAP |
dec [pg_data.pg_mutex] |
mov ecx, pg_data.mutex |
call mutex_unlock |
.ret: |
ret |
endp |
956,25 → 959,7 |
ret |
endp |
; param |
; ebx=mutex |
align 4 |
wait_mutex: |
;;Maxis use atomic bts for mutex 4.4.2009 |
push eax |
push ebx |
.do_wait: |
bts dword [ebx],0 |
jnc .locked |
call change_task |
jmp .do_wait |
.locked: |
pop ebx |
pop eax |
ret |
align 4 |
tls_app_entry: |
call init_heap |
/kernel/branches/Kolibri-acpi/core/timers.inc |
---|
0,0 → 1,205 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision: 2122 $ |
; Simple implementation of timers. All timers are organized in a double-linked |
; list, and the OS loop after every timer tick processes the list. |
; This structure describes a timer for the kernel. |
struct TIMER |
.Next dd ? |
.Prev dd ? |
; These fields organize a double-linked list of all timers. |
.TimerFunc dd ? |
; Function to be called when the timer is activated. |
.UserData dd ? |
; The value that is passed as is to .TimerFunc. |
.Time dd ? |
; Time at which the timer should be activated. |
.Interval dd ? |
; Interval between activations of the timer, in 0.01s. |
ends |
iglobal |
align 4 |
; The head of timer list. |
timer_list: |
dd timer_list |
dd timer_list |
endg |
uglobal |
; These two variables are used to synchronize access to the global list. |
; Logically, they form an recursive mutex. Physically, the first variable holds |
; the slot number of the current owner or 0, the second variable holds the |
; recursion count. |
; The mutex should be recursive to allow a timer function to add/delete other |
; timers or itself. |
timer_list_owner dd 0 |
timer_list_numlocks dd 0 |
; A timer function can delete any timer, including itself and the next timer in |
; the chain. To handle such situation correctly, we keep the next timer in a |
; global variable, so the removing operation can update it. |
timer_next dd 0 |
endg |
; This internal function acquires the lock for the global list. |
lock_timer_list: |
mov edx, [CURRENT_TASK] |
@@: |
xor eax, eax |
lock cmpxchg [timer_list_owner], edx |
jz @f |
cmp eax, edx |
jz @f |
call change_task |
jmp @b |
@@: |
inc [timer_list_numlocks] |
ret |
; This internal function releases the lock for the global list. |
unlock_timer_list: |
dec [timer_list_numlocks] |
jnz .nothing |
mov [timer_list_owner], 0 |
.nothing: |
ret |
; This function adds a timer. |
; If deltaStart is nonzero, the timer is activated after deltaStart hundredths |
; of seconds starting from the current time. If interval is nonzero, the timer |
; is activated every deltaWork hundredths of seconds starting from the first |
; activation. The activated timer calls timerFunc as stdcall function with one |
; argument userData. |
; Return value is NULL if something has failed or some value which is opaque |
; for the caller. Later this value can be used for cancel_timer_hs. |
proc timer_hs stdcall uses ebx, deltaStart:dword, interval:dword, \ |
timerFunc:dword, userData:dword |
; 1. Allocate memory for the TIMER structure. |
; 1a. Call the allocator. |
push sizeof.TIMER |
pop eax |
call malloc |
; 1b. If allocation failed, return (go to 5) with eax = 0. |
test eax, eax |
jz .nothing |
; 2. Setup the TIMER structure. |
xchg ebx, eax |
; 2a. Copy values from the arguments. |
mov ecx, [interval] |
mov [ebx+TIMER.Interval], ecx |
mov ecx, [timerFunc] |
mov [ebx+TIMER.TimerFunc], ecx |
mov ecx, [userData] |
mov [ebx+TIMER.UserData], ecx |
; 2b. Get time of the next activation. |
mov ecx, [deltaStart] |
test ecx, ecx |
jnz @f |
mov ecx, [interval] |
@@: |
add ecx, [timer_ticks] |
mov [ebx+TIMER.Time], ecx |
; 3. Insert the TIMER structure to the global list. |
; 3a. Acquire the lock. |
call lock_timer_list |
; 3b. Insert an item at ebx to the tail of the timer_list. |
mov eax, timer_list |
mov ecx, [eax+TIMER.Prev] |
mov [ebx+TIMER.Next], eax |
mov [ebx+TIMER.Prev], ecx |
mov [eax+TIMER.Prev], ebx |
mov [ecx+TIMER.Next], ebx |
; 3c. Release the lock. |
call unlock_timer_list |
; 4. Return with eax = pointer to TIMER structure. |
xchg ebx, eax |
.nothing: |
; 5. Returning. |
ret |
endp |
; This function removes a timer. |
; The only argument is [esp+4] = the value which was returned from timer_hs. |
cancel_timer_hs: |
push ebx ; save used register to be stdcall |
; 1. Remove the TIMER structure from the global list. |
; 1a. Acquire the lock. |
call lock_timer_list |
mov ebx, [esp+4+4] |
; 1b. Delete an item at ebx from the double-linked list. |
mov eax, [ebx+TIMER.Next] |
mov ecx, [ebx+TIMER.Prev] |
mov [eax+TIMER.Prev], ecx |
mov [ecx+TIMER.Next], eax |
; 1c. If we are removing the next timer in currently processing chain, |
; the next timer for this timer becomes new next timer. |
cmp ebx, [timer_next] |
jnz @f |
mov [timer_next], eax |
@@: |
; 1d. Release the lock. |
call unlock_timer_list |
; 2. Free the TIMER structure. |
xchg eax, ebx |
call free |
; 3. Return. |
pop ebx ; restore used register to be stdcall |
ret 4 ; purge one dword argument to be stdcall |
; This function is regularly called from osloop. It processes the global list |
; and activates the corresponding timers. |
check_timers: |
; 1. Acquire the lock. |
call lock_timer_list |
; 2. Loop over all registered timers, checking time. |
; 2a. Get the first item. |
mov eax, [timer_list+TIMER.Next] |
mov [timer_next], eax |
.loop: |
; 2b. Check for end of list. |
cmp eax, timer_list |
jz .done |
; 2c. Get and store the next timer. |
mov edx, [eax+TIMER.Next] |
mov [timer_next], edx |
; 2d. Check time for timer activation. |
; We can't just compare [timer_ticks] and [TIMER.Time], since overflows are |
; possible: if the current time is 0FFFFFFFFh ticks and timer should be |
; activated in 3 ticks, the simple comparison will produce incorrect result. |
; So we calculate the difference [timer_ticks] - [TIMER.Time]; if it is |
; non-negative, the time is over; if it is negative, then either the time is |
; not over or we have not processed this timer for 2^31 ticks, what is very |
; unlikely. |
mov edx, [timer_ticks] |
sub edx, [eax+TIMER.Time] |
js .next |
; The timer should be activated now. |
; 2e. Store the timer data in the stack. This is required since 2f can delete |
; the timer, invalidating the content. |
push [eax+TIMER.UserData] ; parameter for TimerFunc |
push [eax+TIMER.TimerFunc] ; to be restored in 2g |
; 2f. Calculate time of next activation or delete the timer if it is one-shot. |
mov ecx, [eax+TIMER.Interval] |
add [eax+TIMER.Time], ecx |
test ecx, ecx |
jnz .nodelete |
stdcall cancel_timer_hs, eax |
.nodelete: |
; 2g. Activate timer, using data from the stack. |
pop eax |
call eax |
.next: |
; 2h. Advance to the next timer and continue the loop. |
mov eax, [timer_next] |
jmp .loop |
.done: |
; 3. Release the lock. |
call unlock_timer_list |
; 4. Return. |
ret |
/kernel/branches/Kolibri-acpi/core/v86.inc |
---|
328,7 → 328,7 |
cmp edx, -1 |
jz .noirqhook |
uglobal |
v86_irqhooks rd IRQ_RESERVE * 2 |
v86_irqhooks rd IRQ_RESERVED * 2 |
endg |
cmp [v86_irqhooks+edx*8], 0 |
jz @f |
839,6 → 839,7 |
; mov byte [BOOT_VAR + 48Eh], 0FFh |
; ret |
align 4 |
v86_irq: |
; push irq/pushad/jmp v86_irq |
; eax = irq |