kernel: initial pipe() support

git-svn-id: svn://kolibrios.org@6926 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2017-06-15 22:36:39 +00:00
parent 30022f1ed8
commit af61cc97e8
8 changed files with 610 additions and 250 deletions

View File

@ -413,6 +413,29 @@ FUTEX_DESTROY equ 1
FUTEX_WAIT equ 2
FUTEX_WAKE equ 3
struct FILED
list LHEAD
magic rd 1
handle rd 1
destroy rd 1
file rd 1
ends
struct PIPE
pipe_ops rd 1
buffer rd 1
readers rd 1
writers rd 1
pipe_lock MUTEX
count rd 1
read_end rd 1
write_end rd 1
rlist LHEAD
wlist LHEAD
ends
struct PROC
list LHEAD
thr_list LHEAD

View File

@ -1437,6 +1437,8 @@ destroy_kernel_object:
call free ;release object memory
ret
;void* __fastcall create_object(size_t size)
; param
; ecx= size
@ -1485,3 +1487,33 @@ create_object:
xor eax, eax
ret
;int __fastcall destroy_object(struct object *obj)
align 4
destroy_object:
push esi
mov esi, [current_process]
mov edx, [ecx+FUTEX.handle]
pushfd
cli
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

View File

@ -9,256 +9,7 @@
$Revision$
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
iglobal
align 4
f77call:
dd f77.futex_init ;0
dd f77.futex_destroy ;1
dd f77.futex_wait ;2
dd f77.futex_wake ;3
.end:
endg
align 4
sys_synchronization:
f77:
test ebx, ebx
jz .futex_init
cmp ebx, (f77call.end-f77call)/4
jae .fail
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 [f77call+ebx*4]
.fail:
mov [esp+SYSCALL_STACK._eax], -1
ret
align 4
.futex_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
.futex_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
.futex_wait:
test esi, esi
jnz .futex_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, [TASK_BASE]
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+TASKDATA.state], 1
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
.futex_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], f77.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 eax, [TASK_BASE]
mov [eax+TASKDATA.state], 5
mov [esp+MUTEX_WAITER.task], eax
lea esi, [ebp+FUTEX.wait_list]
list_add_tail esp, esi ;esp= new waiter, esi= list head
.again_timeout:
call change_task
mov eax, [ebx+APPDATA.wait_param]
test eax, eax
jz .timeout
mov eax, edx
lock cmpxchg [ecx], edx
jz .again_timeout
@@:
list_del esp
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
.futex_wake:
xor ecx, ecx
pushfd
cli
lea ebx, [ebp+FUTEX.wait_list]
mov esi, [ebx+LHEAD.next]
.wake:
cmp esi, ebx
je .done
mov eax, [esi+MUTEX_WAITER.task]
mov [eax+TASKDATA.state], 0
mov esi, [esi+MUTEX_WAITER.list.next]
inc ecx
cmp ecx, edx
jb .wake
.done:
popfd
mov [esp+SYSCALL_STACK._eax], ecx
ret
RWSEM_WAITING_FOR_WRITE equ 0
RWSEM_WAITING_FOR_READ equ 1

View File

@ -175,7 +175,7 @@ iglobal
dd sys_network ; 74-reserved for new stack
dd sys_socket ; 75-reserved for new stack
dd sys_protocols ; 76-reserved for new stack
dd sys_synchronization ; 77
dd sys_posix ; posix support
dd undefined_syscall ; 78-free
dd undefined_syscall ; 79-free
dd fileSystemUnicode ; 80-File system interface for different encodings

View File

@ -27,6 +27,8 @@ include "core/apic.inc"
include "core/timers.inc"
include "core/clipboard.inc"
include "posix/posix.inc"
include "boot/shutdown.inc" ; kernel shutdown
include "video/vesa20.inc"

View File

@ -0,0 +1,245 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2017. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 6917 $
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, [TASK_BASE]
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+TASKDATA.state], 1
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 eax, [TASK_BASE]
mov [eax+TASKDATA.state], 5
mov [esp+MUTEX_WAITER.task], eax
lea esi, [ebp+FUTEX.wait_list]
list_add_tail esp, esi ;esp= new waiter, esi= list head
.again_timeout:
call change_task
mov eax, [ebx+APPDATA.wait_param]
test eax, eax
jz .timeout
mov eax, edx
lock cmpxchg [ecx], edx
jz .again_timeout
@@:
list_del esp
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+TASKDATA.state], 0
mov esi, [esi+MUTEX_WAITER.list.next]
inc ecx
cmp ecx, edx
jb .again_wake
.done:
popfd
mov [esp+SYSCALL_STACK._eax], ecx
ret

210
kernel/trunk/posix/pipe.inc Normal file
View File

@ -0,0 +1,210 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2017. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 6917 $
O_CLOEXEC equ 0x40000
PIPE_BUFFER_SIZE equ 4096
iglobal
align 4
pipe_file_ops:
dd pipe_close ;0
dd pipe_read ;1
dd pipe_write ;2
endg
;int pipe2(int pipefd[2], int flags);
;ecx pipefd
;edx flags
align 4
sys_pipe2:
.pipeflags equ esp+16
.pipefd equ esp+12
.fdread equ esp+8
.fdwrite equ esp+4
.intpipe equ esp
push ebp
test ecx, ecx
mov ebp, -EFAULT
js .fail
test edx, not O_CLOEXEC
mov ebp, -EINVAL
jnz .fail
push ecx
push edx
sub esp, (5-2)*4
mov ecx, sizeof.FILED
call create_object
mov [.fdread], eax
test eax, eax
mov ebp, -EMFILE
jz .err_0
mov ecx, sizeof.FILED
call create_object
mov [.fdwrite], eax
test eax, eax
jz .err_1
mov eax, sizeof.PIPE
call malloc
test eax, eax
mov ebp, -ENFILE
jz .err_2
mov ebp, eax
stdcall create_ring_buffer, PIPE_BUFFER_SIZE, PG_SWR
test eax, eax
jz .err_3
mov [ebp+PIPE.pipe_ops], pipe_file_ops
mov [ebp+PIPE.buffer], eax
xor eax, eax
mov [ebp+PIPE.count], eax
mov [ebp+PIPE.read_end], eax
mov [ebp+PIPE.write_end], eax
inc eax
mov [ebp+PIPE.readers], eax
mov [ebp+PIPE.writers], eax
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_init
lea ecx, [ebp+PIPE.rlist]
list_init ecx
lea ecx, [ebp+PIPE.wlist]
list_init ecx
mov eax, [.fdread]
mov edx, [.fdwrite]
mov ecx, [.pipefd]
mov [eax+FILED.magic], 'PIPE'
mov [eax+FILED.destroy], 0
mov [eax+FILED.file], ebp
mov [edx+FILED.magic], 'PIPE'
mov [edx+FILED.destroy], 0
mov [edx+FILED.file], ebp
mov [ecx], eax
mov [ecx+4], edx
add esp, 5*4
pop ebp
xor eax, eax
mov [esp+SYSCALL_STACK._eax], eax
ret
.err_3:
mov eax, ebp
call free
mov ebp, -ENFILE
.err_2:
mov ecx, [.fdwrite]
call destroy_object
.err_1:
mov ecx, [.fdread]
call destroy_object
.err_0:
add esp, 5*4
.fail:
mov [esp+SYSCALL_STACK._eax], ebp
pop ebp
ret
purge .pipeflags
purge .filefd
purge .fdread
purge .fdwrite
purge .intpipe
; edx buf
; esi count
; ebp pipe
align 4
pipe_read:
mov edi, edx
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_lock
xor eax, eax
cmp eax, [ebp+PIPE.writers]
je .eof
mov ecx, [ebp+PIPE.count]
test ecx, ecx
jz .wait
.check_count:
cmp ecx, esi
jb .read
mov ecx, esi
.read:
mov esi, [ebp+PIPE.buffer]
add esi, [ebp+PIPE.read_end]
mov [esp+SYSCALL_STACK._eax], ecx
sub [ebp+PIPE.count], ecx
cld
rep stosb
and esi, 0xFFF
add [ebp+PIPE.read_end], esi
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock
ret
.wait:
sub esp, sizeof.MUTEX_WAITER
mov ebx, [TASK_BASE]
mov [esp+MUTEX_WAITER.task], ebx
lea edx, [ebp+PIPE.rlist]
list_add_tail esp, edx ;esp= new waiter, edx= list head
.again:
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock
mov [ebx+TASKDATA.state], 1
call change_task
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_lock
mov ecx, [ebp+PIPE.count]
test ecx, ecx
jz .again
list_del esp
add esp, sizeof.MUTEX_WAITER
jmp .check_count
.eof:
mov [esp+SYSCALL_STACK._eax], eax
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock
ret
align 4
pipe_close:
pipe_write:
mov [esp+SYSCALL_STACK._eax], -EBADF
ret

View File

@ -0,0 +1,97 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2017. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 6917 $
ENOENT equ 2
EBADF equ 9
EFAULT equ 14
;EINVAL equ 22 11 defined in stack.inc
ENFILE equ 23
EMFILE equ 24
FILEOP_CLOSE equ 0
FILEOP_READ equ 1
FILEOP_WRITE equ 2
include "futex.inc"
iglobal
align 4
sys_futex_call:
dd sys_futex.destroy ;1
dd sys_futex.wait ;2
dd sys_futex.wake ;3
dd sys_futex.requeue ;4
dd sys_futex.cmp_requeue ;5
dd sys_futex.wait_bitset ;6
dd sys_futex.wake_bitset ;7
endg
include "pipe.inc"
iglobal
align 4
sys_posix_call:
dd sys_futex.init ;0 futex_init
dd sys_futex ;1 futex_destroy
dd sys_futex ;2 futex_wait
dd sys_futex ;3 futex_wake
dd sys_futex ;4 reserved
dd sys_futex ;5 reserved
dd sys_futex ;6 reserved
dd sys_futex ;7 reserved
dd sys_posix.fail ;8 sys_open
dd sys_posix.fail ;9 sys_close
dd sys_posix.fail ;10 sys_read
dd sys_posix.fail ;11 sys_write
dd sys_posix.fail ;12 sys_dup3
dd sys_pipe2 ;13
.end:
endg
align 4
sys_posix:
cmp ebx, (sys_posix_call.end-sys_posix_call)/4
jae .fail
jmp dword [sys_posix_call+ebx*4]
.fail:
mov [esp+SYSCALL_STACK._eax], -EBADF
ret
;ssize_t read(int fd, void *buf, size_t count);
; ecx fd
; edx buf
; esi count
align 4
sys_read:
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+FILED.magic], 'PIPE'
jne .fail
cmp [ebp+FILED.handle], ecx
jne .fail
mov ebp, [ebp+FILED.file]
mov eax, [ebp]
jmp dword [eax+FILEOP_READ*4]
.fail:
mov [esp+SYSCALL_STACK._eax], -EBADF
ret