kolibrios/kernel/trunk/posix/futex.inc

243 lines
5.5 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
;struct futex* __fastcall create_futex(int *ptr)
create_futex:
push ecx
mov ecx, sizeof.FUTEX
call create_object
pop ecx
test eax, eax
jz .fail
mov [eax + FUTEX.magic], 'FUTX'
mov [eax + FUTEX.destroy], 0
mov [eax + FUTEX.pointer], ecx
lea ecx, [eax + FUTEX.wait_list]
list_init ecx
mov [eax + FUTEX.flags], 0
.fail:
ret
align 4
;int __fastcall destroy_futex(struct futex *futex)
destroy_futex:
push esi
mov esi, [current_process]
mov edx, [ecx + FUTEX.handle]
pushfd
cli
lea eax, [ecx + FUTEX.wait_list]
cmp eax, [eax + LHEAD.next]
jne .fail
mov eax, [esi + PROC.ht_next]
mov [esi + PROC.htab + edx*4], eax
mov [esi + PROC.ht_next], edx
inc [esi + PROC.ht_free]
popfd
pop esi
mov eax, ecx
call free
xor eax, eax
ret
.fail:
popfd
pop esi
mov eax, -1
ret
align 4
sys_futex:
cmp ecx, STDERR_FILENO
jbe .fail
cmp ecx, (PROC.pdt_0 - PROC.htab)/4
jae .fail
mov edi, [current_process]
mov ebp, [edi + PROC.htab + ecx*4]
cmp [ebp + FUTEX.magic], 'FUTX'
jne .fail
cmp [ebp + FUTEX.handle], ecx
jne .fail
jmp dword [sys_futex_call + ebx*4-4]
.fail:
.requeue:
.cmp_requeue:
.wait_bitset:
.wake_bitset:
mov [esp + SYSCALL_STACK.eax], -1
ret
align 4
.init:
call create_futex
test eax, eax
jz @F
mov eax, [eax + FUTEX.handle]
@@:
mov [esp + SYSCALL_STACK.eax], eax
ret
align 4
;ecx futex handle
;edi current process
;ebp futex object
.destroy:
mov ecx, ebp
call destroy_futex
mov [esp + SYSCALL_STACK.eax], eax
ret
align 4
;ecx futex handle
;edx control value
;esi timeout
;edi current process
;ebp futex object
.wait:
test esi, esi
jnz .wait_timeout
mov ecx, [ebp + FUTEX.pointer]
mov eax, edx
lock cmpxchg [ecx], edx
je .wait_slow
mov [esp + SYSCALL_STACK.eax], -2
ret
.wait_slow:
pushfd
cli
sub esp, sizeof.MUTEX_WAITER
mov ebx, [current_slot]
mov [esp + MUTEX_WAITER.task], ebx
lea esi, [ebp + FUTEX.wait_list]
list_add_tail esp, esi ;esp= new waiter, esi= list head
mov eax, edx
.again:
mov [ebx + APPDATA.state], TSTATE_RUN_SUSPENDED
call change_task
lock cmpxchg [ecx], edx
je .again
list_del esp
add esp, sizeof.MUTEX_WAITER
popfd
mov [esp + SYSCALL_STACK.eax], 0
ret
align 4
;ecx futex handle
;edx control value
;esi timeout
;edi current process
;ebp futex object
.wait_timeout:
mov ecx, [ebp + FUTEX.pointer]
mov eax, edx
lock cmpxchg [ecx], edx ;wait until old_value == new_value
je .wait_slow_timeout
mov [esp + SYSCALL_STACK.eax], -2
ret
align 4
.wait_test:
xor eax, eax
ret
.wait_slow_timeout:
pushfd
cli
sub esp, sizeof.MUTEX_WAITER
mov ebx, [current_slot]
mov [ebx + APPDATA.wait_test], sys_futex.wait_test
mov [ebx + APPDATA.wait_timeout], esi
mov [ebx + APPDATA.wait_param], ebp
mov eax, [timer_ticks]
mov [ebx + APPDATA.wait_begin], eax
mov [ebx + APPDATA.state], TSTATE_WAITING
mov [esp + MUTEX_WAITER.task], ebx
lea esi, [ebp + FUTEX.wait_list]
list_add_tail esp, esi ;esp= new waiter, esi= list head
.again_timeout:
mov [ebx + APPDATA.state], TSTATE_WAITING
call change_task
mov eax, [ebx + APPDATA.wait_param]
test eax, eax
jz .timeout
mov eax, edx
lock cmpxchg [ecx], edx
jz .again_timeout
@@:
cli
list_del esp
sti
add esp, sizeof.MUTEX_WAITER
popfd
mov [esp + SYSCALL_STACK.eax], 0
ret
.timeout:
list_del esp
add esp, sizeof.MUTEX_WAITER
popfd
mov [esp + SYSCALL_STACK.eax], -1
ret
align 4
;ecx futex handle
;edx number of threads
;edi current process
;ebp futex object
.wake:
xor ecx, ecx
pushfd
cli
lea ebx, [ebp + FUTEX.wait_list]
mov esi, [ebx + LHEAD.next]
.again_wake:
cmp esi, ebx
je .done
mov eax, [esi + MUTEX_WAITER.task]
mov [eax + APPDATA.state], TSTATE_RUNNING
mov esi, [esi + MUTEX_WAITER.list.next]
inc ecx
cmp ecx, edx
jb .again_wake
.done:
popfd
mov [esp + SYSCALL_STACK.eax], ecx
ret