From af61cc97e8b62c56a4ae9929cfae0087de6f7175 Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Thu, 15 Jun 2017 22:36:39 +0000 Subject: [PATCH] kernel: initial pipe() support git-svn-id: svn://kolibrios.org@6926 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/const.inc | 23 ++++ kernel/trunk/core/dll.inc | 32 +++++ kernel/trunk/core/sync.inc | 249 ---------------------------------- kernel/trunk/core/syscall.inc | 2 +- kernel/trunk/kernel32.inc | 2 + kernel/trunk/posix/futex.inc | 245 +++++++++++++++++++++++++++++++++ kernel/trunk/posix/pipe.inc | 210 ++++++++++++++++++++++++++++ kernel/trunk/posix/posix.inc | 97 +++++++++++++ 8 files changed, 610 insertions(+), 250 deletions(-) create mode 100644 kernel/trunk/posix/futex.inc create mode 100644 kernel/trunk/posix/pipe.inc create mode 100644 kernel/trunk/posix/posix.inc diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index 7683b1d1b0..3b0997a95a 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -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 diff --git a/kernel/trunk/core/dll.inc b/kernel/trunk/core/dll.inc index 5811e648d8..076af84b03 100644 --- a/kernel/trunk/core/dll.inc +++ b/kernel/trunk/core/dll.inc @@ -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 + diff --git a/kernel/trunk/core/sync.inc b/kernel/trunk/core/sync.inc index 969e9505a9..64a08e0cb9 100644 --- a/kernel/trunk/core/sync.inc +++ b/kernel/trunk/core/sync.inc @@ -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 diff --git a/kernel/trunk/core/syscall.inc b/kernel/trunk/core/syscall.inc index 015f1015b9..83f6354018 100644 --- a/kernel/trunk/core/syscall.inc +++ b/kernel/trunk/core/syscall.inc @@ -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 diff --git a/kernel/trunk/kernel32.inc b/kernel/trunk/kernel32.inc index d7b32b9338..19aa728ea8 100644 --- a/kernel/trunk/kernel32.inc +++ b/kernel/trunk/kernel32.inc @@ -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" diff --git a/kernel/trunk/posix/futex.inc b/kernel/trunk/posix/futex.inc new file mode 100644 index 0000000000..932e5b0f64 --- /dev/null +++ b/kernel/trunk/posix/futex.inc @@ -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 + diff --git a/kernel/trunk/posix/pipe.inc b/kernel/trunk/posix/pipe.inc new file mode 100644 index 0000000000..097085ce7e --- /dev/null +++ b/kernel/trunk/posix/pipe.inc @@ -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 diff --git a/kernel/trunk/posix/posix.inc b/kernel/trunk/posix/posix.inc new file mode 100644 index 0000000000..05d905b1f7 --- /dev/null +++ b/kernel/trunk/posix/posix.inc @@ -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 +