/kernel/trunk/const.inc |
---|
413,6 → 413,29 |
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 |
/kernel/trunk/core/dll.inc |
---|
1437,6 → 1437,8 |
call free ;release object memory |
ret |
;void* __fastcall create_object(size_t size) |
; param |
; ecx= size |
1485,3 → 1487,33 |
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 |
/kernel/trunk/core/sync.inc |
---|
9,257 → 9,8 |
$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 |
/kernel/trunk/core/syscall.inc |
---|
175,7 → 175,7 |
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 |
/kernel/trunk/kernel32.inc |
---|
27,6 → 27,8 |
include "core/timers.inc" |
include "core/clipboard.inc" |
include "posix/posix.inc" |
include "boot/shutdown.inc" ; kernel shutdown |
include "video/vesa20.inc" |
/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 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/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 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/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 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |