kernel: pipes - improved synchronization

git-svn-id: svn://kolibrios.org@6929 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2017-06-16 22:47:00 +00:00
parent 65af271ccd
commit 8b1036ed49
3 changed files with 101 additions and 23 deletions

View File

@ -418,6 +418,7 @@ struct FILED
magic rd 1 magic rd 1
handle rd 1 handle rd 1
destroy rd 1 destroy rd 1
mode rd 1
file rd 1 file rd 1
ends ends

View File

@ -7,6 +7,9 @@
$Revision: 6917 $ $Revision: 6917 $
F_READ equ 0x0001 ; file opened for reading
F_WRITE equ 0x0002 ; file opened for writing
O_CLOEXEC equ 0x40000 O_CLOEXEC equ 0x40000
PIPE_BUFFER_SIZE equ 4096 PIPE_BUFFER_SIZE equ 4096
@ -96,10 +99,12 @@ sys_pipe2:
mov [eax+FILED.magic], 'PIPE' mov [eax+FILED.magic], 'PIPE'
mov [eax+FILED.destroy], 0 mov [eax+FILED.destroy], 0
mov [eax+FILED.mode], F_READ
mov [eax+FILED.file], ebp mov [eax+FILED.file], ebp
mov [edx+FILED.magic], 'PIPE' mov [edx+FILED.magic], 'PIPE'
mov [edx+FILED.destroy], 0 mov [edx+FILED.destroy], 0
mov [edx+FILED.mode], F_WRITE
mov [edx+FILED.file], ebp mov [edx+FILED.file], ebp
mov eax, [eax+FILED.handle] mov eax, [eax+FILED.handle]
@ -125,8 +130,9 @@ sys_pipe2:
.err_0: .err_0:
add esp, 5*4 add esp, 5*4
.fail: .fail:
mov [esp+SYSCALL_STACK._eax], ebp mov eax, ebp
pop ebp pop ebp
mov [esp+SYSCALL_STACK._eax], eax
ret ret
purge .pipeflags purge .pipeflags
@ -136,18 +142,18 @@ purge .fdwrite
purge .intpipe purge .intpipe
; edx buf ; edx dst_buf
; esi count ; esi read count
; ebp pipe ; ebp pipe
align 4 align 4
pipe_read: pipe_read:
mov edi, edx mov edi, edx
.again:
lea ecx, [ebp+PIPE.pipe_lock] lea ecx, [ebp+PIPE.pipe_lock]
call mutex_lock call mutex_lock
.again:
xor eax, eax xor eax, eax
cmp eax, [ebp+PIPE.writers] cmp eax, [ebp+PIPE.writers]
je .eof je .eof
@ -170,11 +176,31 @@ pipe_read:
and esi, 0xFFF and esi, 0xFFF
mov [ebp+PIPE.read_end], esi mov [ebp+PIPE.read_end], esi
lea ecx, [ebp+PIPE.wlist]
cmp ecx, [ebp+PIPE.wlist.next]
je @F
mov ecx, [ecx+MUTEX_WAITER.task]
mov [ecx+TASKDATA.state], 0 ;activate writer task
@@:
cmp [ebp+PIPE.count], 0
je @F
lea eax, [ebp+PIPE.rlist]
cmp eax, [ebp+PIPE.rlist.next]
je @F
mov eax, [eax+MUTEX_WAITER.task]
mov [eax+TASKDATA.state], 0 ;activate reader task
@@:
lea ecx, [ebp+PIPE.pipe_lock] lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock call mutex_unlock
ret ret
.wait: .wait:
pushfd
cli
sub esp, sizeof.MUTEX_WAITER sub esp, sizeof.MUTEX_WAITER
mov ebx, [TASK_BASE] mov ebx, [TASK_BASE]
mov [esp+MUTEX_WAITER.task], ebx mov [esp+MUTEX_WAITER.task], ebx
@ -188,8 +214,12 @@ pipe_read:
mov [ebx+TASKDATA.state], 1 mov [ebx+TASKDATA.state], 1
call change_task call change_task
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_lock
list_del esp list_del esp
add esp, sizeof.MUTEX_WAITER add esp, sizeof.MUTEX_WAITER
popfd
jmp .again jmp .again
.eof: .eof:
@ -198,49 +228,85 @@ pipe_read:
call mutex_unlock call mutex_unlock
ret ret
; edx buf ; edx src_buf
; esi count ; esi write count
; ebp pipe ; ebp pipe
align 4 align 4
pipe_write: pipe_write:
mov edi, edx
.again: .written equ esp
push 0 ;written
mov ebx, esi ;ebx = write count
mov esi, edx ;esi = src
lea ecx, [ebp+PIPE.pipe_lock] lea ecx, [ebp+PIPE.pipe_lock]
call mutex_lock call mutex_lock
.again:
xor eax, eax xor eax, eax
cmp eax, [ebp+PIPE.readers] cmp eax, [ebp+PIPE.readers]
je .epipe je .epipe
mov ecx, [ebp+PIPE.count] mov ecx, 4096
sub ecx, 4096 sub ecx, [ebp+PIPE.count]
jz .wait jz .wait ;wait if buffer full
.check_count: .check_count:
cmp ecx, esi cmp ecx, ebx
jb .write jb .write
mov ecx, esi mov ecx, ebx
.write: .write:
mov esi, edi
mov edi, [ebp+PIPE.buffer] mov edi, [ebp+PIPE.buffer]
add edi, [ebp+PIPE.write_end] add edi, [ebp+PIPE.write_end]
mov [esp+SYSCALL_STACK._eax], ecx add [.written], ecx
sub ebx, ecx
add [ebp+PIPE.count], ecx add [ebp+PIPE.count], ecx
cld cld
rep movsb rep movsb
and edi, 0xFFF and edi, 0xFFF
mov [ebp+PIPE.write_end], edi mov [ebp+PIPE.write_end], edi
pushfd
cli
lea eax, [ebp+PIPE.rlist]
cmp eax, [ebp+PIPE.rlist.next]
je @F
mov eax, [eax+MUTEX_WAITER.task]
mov [eax+TASKDATA.state], 0 ;activate reader task
@@:
cmp [ebp+PIPE.count], 4096
je @F
lea ecx, [ebp+PIPE.wlist]
cmp ecx, [ebp+PIPE.wlist.next]
je @F
mov ecx, [eax+MUTEX_WAITER.task]
mov [ecx+TASKDATA.state], 0 ;activate writer task
@@:
popfd
lea ecx, [ebp+PIPE.pipe_lock] lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock call mutex_unlock
test ebx, ebx
jnz .again
pop eax ; written
mov [esp+SYSCALL_STACK._eax], eax
ret ret
.wait: .wait:
pushfd
cli
sub esp, sizeof.MUTEX_WAITER sub esp, sizeof.MUTEX_WAITER
mov ebx, [TASK_BASE] mov ecx, [TASK_BASE]
mov [esp+MUTEX_WAITER.task], ebx mov [esp+MUTEX_WAITER.task], ecx
lea edx, [ebp+PIPE.wlist] lea edx, [ebp+PIPE.wlist]
list_add_tail esp, edx ;esp= new waiter, edx= list head list_add_tail esp, edx ;esp= new waiter, edx= list head
@ -248,17 +314,23 @@ pipe_write:
lea ecx, [ebp+PIPE.pipe_lock] lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock call mutex_unlock
mov [ebx+TASKDATA.state], 1 mov [ecx+TASKDATA.state], 1
call change_task call change_task
lea ecx, [ebp+PIPE.pipe_lock]
call mutex_lock
list_del esp list_del esp
add esp, sizeof.MUTEX_WAITER add esp, sizeof.MUTEX_WAITER
popfd
jmp .again jmp .again
.epipe: .epipe:
mov [esp+SYSCALL_STACK._eax], -EPIPE
lea ecx, [ebp+PIPE.pipe_lock] lea ecx, [ebp+PIPE.pipe_lock]
call mutex_unlock call mutex_unlock
add esp, 4
mov [esp+SYSCALL_STACK._eax], -EPIPE
ret ret
align 4 align 4

View File

@ -88,6 +88,9 @@ sys_read:
cmp [ebp+FILED.handle], ecx cmp [ebp+FILED.handle], ecx
jne .fail jne .fail
test [ebp+FILED.mode], F_READ
jz .fail
mov ebp, [ebp+FILED.file] mov ebp, [ebp+FILED.file]
mov eax, [ebp] mov eax, [ebp]
jmp dword [eax+FILEOP_READ*4] jmp dword [eax+FILEOP_READ*4]
@ -114,6 +117,8 @@ sys_write:
jne .fail jne .fail
cmp [ebp+FILED.handle], ecx cmp [ebp+FILED.handle], ecx
jne .fail jne .fail
test [ebp+FILED.mode], F_WRITE
jz .fail
mov ebp, [ebp+FILED.file] mov ebp, [ebp+FILED.file]
mov eax, [ebp] mov eax, [ebp]