Compare commits

...

6 commits

Author SHA1 Message Date
root
fc1cc26b0f rewrite client__pollout
algorithm:
1. call client__pollout__before_fresh_lines
2. if error, return
3. find line length
4. if no line, set POLLIN and goto 8
5. call client__pollout__line
6. if error, goto 7
7. finished with this line; goto 3
8. move the final incomplete line to the start of the client's buffer
9. return
2025-05-21 09:32:25 +00:00
root
c16c82b15f server.s: use r15 not r10 for persisting thru syscalls 2025-05-21 09:08:43 +00:00
root
e31c9452c8 remove eagain experiment 2025-05-21 09:08:43 +00:00
root
21153b7d14 EAGAIN in constants.c 2025-05-21 09:08:32 +00:00
root
2a59922c01 succeed at finding EAGAIN by experiment: -11 2025-05-18 13:13:50 +00:00
root
56715c3079 fail to find EAGAIN by experiment 2025-05-18 13:13:13 +00:00
4 changed files with 221 additions and 58 deletions

221
client.s
View file

@ -70,83 +70,226 @@ client__pollin__line_too_long:
jmp client__pollin__return jmp client__pollin__return
; Returns:
; rax - non-negative from write(2)
; Errors: ; Errors:
; rax - -1024 - no line was buffered ; rax - negative or zero - from write(2)
; rax - other negative - from write(2)
; Arguments: ; Arguments:
; rdi - fd ; rdi - fd
; rsi - address of client within clients array ; rsi - address of client within clients array
; rdx - pollfds index ; rdx - pollfds index
; Variables: ; Variables:
; rbp - fd
; rbx - pollfds index ; rbx - pollfds index
; r12 - address of client within clients array ; r12 - address of client within clients array
; r13 - line length ; r13 - line start
; r11 - client buffer end of text after call to write(2) ; r14 - line end
; r15 - client buffer end
; r11 - client buffer, length of last incomplete line
client__pollout: client__pollout:
push rbp
push rbx push rbx
push r12 push r12
push r13 push r13
push r14
push r15
mov rbp, rdi
mov rbx, rdx mov rbx, rdx
mov r12, rsi mov r12, rsi
mov r13, rsi
add r13, OFFSET_CLIENT_BUFFER
mov r15, r13
add r15, 255
push rdi mov rdi, rbp
mov rdi, r12
add rdi, OFFSET_CLIENT_BUFFER
mov rsi, 255
call scanline
pop rdi
; poll(2)'d for POLLOUT but we had no line buffered;
; should be impossible
cmp rax, 0
je client__pollout__no_line
mov r13, rax
mov rax, SYS_WRITE
mov rsi, r12 mov rsi, r12
add rsi, OFFSET_CLIENT_BUFFER call client__pollout__before_fresh_lines
mov rdx, r13
syscall
; error from write(2)
cmp rax, 0 cmp rax, 0
jl client__pollout__return jle client__pollout__return
mov r10, r12 client__pollout__scan:
mov rdi, r13
mov rsi, 0
mov sil, [r12 + OFFSET_CLIENT_BUFFER_LEN]
call scanline
cmp rax, 0
jle client__pollout__set_pollin ; no lines left
sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al
; line_end = line_start + line_len
mov r14, r13
add r14, rax
mov rdi, rbp
mov rsi, r12
mov rdx, r13
mov rcx, r14
sub rcx, r13
call client__pollout__line
mov r13, r14
cmp rax, 0
jle client__pollout__shunt
jmp client__pollout__scan
client__pollout__set_pollin:
mov word [pollfds + rbx * pollfd_size + 4], POLLIN
mov rax, 1
client__pollout__shunt:
mov r10, 0
mov r11, 0 mov r11, 0
mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN] mov r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN]
add r11, r12 add r11, r12
sub r11, rax add r11, OFFSET_CLIENT_BUFFER
sub r11, r13
client__pollout__shunt: client__pollout__shunt__loop:
cmp r10, r11 cmp r10, r11
jge client__pollout__shunt__finished jge client__pollout__shunt__finished
mov r8b, [r10 + rax] mov r8b, [r10 + r13]
mov [r10], r8b mov [r10], r8b
add r10, 1 add r10, 1
jmp client__pollout__shunt jmp client__pollout__shunt__loop
client__pollout__shunt__finished: client__pollout__shunt__finished:
; buffer_len -= rax mov r10, r13
sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al sub r10, r12
cmp rax, r13 sub r10, OFFSET_CLIENT_BUFFER
jl client__pollout__return
mov word [pollfds + rbx * pollfd_size + 4], POLLIN
client__pollout__return: client__pollout__return:
pop r15
pop r14
pop r13 pop r13
pop r12 pop r12
pop rbx pop rbx
pop rbp
ret ret
client__pollout__no_line: ; Errors:
mov rax, -1024 ; rax - -1024 - some scratch buffer bytes remain, stop write(2)ing
jmp client__pollout__return ; rax - other negative or zero - from write(2)
; Arguments:
; rdi - fd
; rsi - address of client within clients array
client__pollout__before_fresh_lines:
mov rdx, 0
mov dl, [rsi + OFFSET_CLIENT_SCRATCH_LEN]
cmp rdx, 0
jle client__pollout__before_fresh_lines__return__succ
mov rax, SYS_WRITE
push rdx
add rsi, OFFSET_CLIENT_SCRATCH
push rsi
syscall
pop rsi
pop rdx
cmp rax, 0
jle return
sub [rsi - OFFSET_CLIENT_SCRATCH + OFFSET_CLIENT_SCRATCH_LEN], al
mov r10, rsi
mov r11, rsi
add r11, rdx
sub r11, rax
client__pollout__before_fresh_lines__shunt:
cmp r10, r11
jge client__pollout__before_fresh_lines__return
mov r8b, [r10 + rax]
mov [r10], r8b
add r10, 1
jmp client__pollout__before_fresh_lines__shunt
client__pollout__before_fresh_lines__return:
cmp rax, rdx
jl client__pollout__before_fresh_lines__return__fail
client__pollout__before_fresh_lines__return__succ:
mov rax, 1
ret
client__pollout__before_fresh_lines__return__fail:
mov rax, -1024
ret
; Errors:
; rax - negative or zero - from write(2)
; Arguments:
; rdi - fd
; rsi - address of client within clients array
; rdx - line start
; rcx - line length
; Variables:
; rsi - client scratch
; r10 - line write(2) end
; r9 - line end
; Assumptions:
; scratch is empty, bc it was emptied by client__pollout__before_fresh_lines
; we must deal with the whole line we are given
client__pollout__line:
; TODO we've got a line
; - try writing it
; - if socket is fucked: return
; - if ok: cool
; - if couldn't do the whole thing: you have scratch available, if it's needed for the protocol
push rdx
push rcx
mov rax, SYS_WRITE
mov rsi, rdx
mov rdx, rcx
syscall
pop rcx
pop rdx
; TODO continue here also not sure calling fn is correct yet
; check that changes to server.s haven't fucked anything up
; error from write(2)
cmp rax, 0
jl client__pollout__line__error
cmp rax, rcx
jl client__pollout__line__incomplete
mov rax, 1
ret
client__pollout__line__error:
mov r10, 0
jmp client__pollout__line__write_scratch
client__pollout__line__incomplete:
mov r10, rax
client__pollout__line__write_scratch:
add rsi, OFFSET_CLIENT_SCRATCH
add r10, rdx
mov r11, 0
mov r9, rcx
add r9, rdx
client__pollout__line__write_scratch__loop:
cmp r10, r9
jge return
mov r8b, [r10 + r11]
mov [rsi + r11], r8b
add r11, 1
jmp client__pollout__line__write_scratch__loop
; Arguments:
; rdi - fd ; rdi - fd
client__shutdown_close: client__shutdown_close:
mov rax, SYS_SHUTDOWN mov rax, SYS_SHUTDOWN

View file

@ -2,6 +2,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <errno.h>
// printf("x %d\n", x); // printf("x %d\n", x);
void main() { void main() {
@ -17,4 +18,6 @@ void main() {
printf("POLLERR %d\n", POLLERR); printf("POLLERR %d\n", POLLERR);
printf("POLLNVAL %d\n", POLLNVAL); printf("POLLNVAL %d\n", POLLNVAL);
printf("SHUT_RDWR %d\n", SHUT_RDWR); printf("SHUT_RDWR %d\n", SHUT_RDWR);
printf("EAGAIN %d\n", EAGAIN);
printf("EWOULDBLOCK %d\n", EWOULDBLOCK);
} }

15
main.s
View file

@ -26,6 +26,7 @@ POLLERR equ 8
POLLNVAL equ 32 POLLNVAL equ 32
; TODO(?) POLLPRI: see poll(2), tcp(7) ; TODO(?) POLLPRI: see poll(2), tcp(7)
SHUT_RDWR equ 2 SHUT_RDWR equ 2
EAGAIN equ -11
;STATE_READING equ 0 ;STATE_READING equ 0
;STATE_WRITING equ 1 ;STATE_WRITING equ 1
@ -34,14 +35,18 @@ SHUT_RDWR equ 2
OFFSET_CLIENT_FD equ 0 OFFSET_CLIENT_FD equ 0
OFFSET_CLIENT_STATE equ 4 OFFSET_CLIENT_STATE equ 4
OFFSET_CLIENT_BUFFER_LEN equ 5 OFFSET_CLIENT_BUFFER_LEN equ 5
OFFSET_CLIENT_BUFFER equ 6 OFFSET_CLIENT_SCRATCH_LEN equ 6
OFFSET_CLIENT_BUFFER equ 7
OFFSET_CLIENT_SCRATCH equ 7 + client_buffer_size
pollfd_size equ 4 + 2 + 2 ; $ man 2 poll pollfd_size equ 4 + 2 + 2 ; $ man 2 poll
pollfds_capacity equ 100 pollfds_capacity equ 100
client_buffer_size equ 255 client_buffer_size equ 255
; fd, state, buffer_len, buffer client_scratch_size equ 255
client_size equ 4 + 2 + client_buffer_size
; fd, state, buffer_len, scratch_len, buffer, scratch
client_size equ 4 + 2 + client_buffer_size + client_scratch_size
clients_capacity equ pollfds_capacity - 1 clients_capacity equ pollfds_capacity - 1
SECTION .data SECTION .data
@ -158,8 +163,12 @@ _client__pollout:
mov rsi, r12 mov rsi, r12
mov rdx, r15 mov rdx, r15
call client__pollout call client__pollout
cmp rax, EAGAIN
je _client__pollout__finished
cmp rax, 0 cmp rax, 0
jle _client__error_or_eof jle _client__error_or_eof
_client__pollout__finished:
add r15, 1 add r15, 1
jmp scan__loop jmp scan__loop

View file

@ -9,53 +9,61 @@ make_server:
mov rsi, SOCK_STREAM mov rsi, SOCK_STREAM
mov rdx, 0 mov rdx, 0
syscall syscall
push rax
push r15
mov r15, rax
mov rdi, r15
call nonblocking call nonblocking
mov rdi, r15
call make_sockaddr call make_sockaddr
pop r10
mov rax, SYS_BIND mov rax, SYS_BIND
mov rdi, r10 mov rdi, r15
mov rsi, sockaddr mov rsi, sockaddr
mov rdx, sockaddr_size mov rdx, sockaddr_size
syscall syscall
mov rax, SYS_LISTEN mov rax, SYS_LISTEN
mov rdi, r10 mov rdi, r15
mov rsi, 100 mov rsi, 100
syscall syscall
mov rax, r10 mov rax, r15
pop r15
ret ret
; rdi - fd
nonblocking: nonblocking:
mov r10, rax push r15
mov r15, rdi
mov rax, SYS_FCNTL mov rax, SYS_FCNTL
mov rdi, r10 mov rdi, r15
mov rsi, F_GETFL mov rsi, F_GETFL
syscall syscall
mov r11, rax mov r10, rax
xor r11, O_NONBLOCK or r10, O_NONBLOCK
mov rax, SYS_FCNTL mov rax, SYS_FCNTL
mov rdi, r10 mov rdi, r15
mov rsi, F_SETFL mov rsi, F_SETFL
mov rdx, r11 mov rdx, r10
syscall syscall
pop r15
ret ret
make_sockaddr: make_sockaddr:
mov word [sockaddr], AF_UNIX mov word [sockaddr], AF_UNIX
mov rax, 0 mov r10, 0
make_sockaddr__copy_server_path: make_sockaddr__copy_server_path:
cmp rax, server_path_len cmp r10, server_path_len
jge return jge return
mov r10, [server_path + rax] mov r8b, [server_path + r10]
mov [sockaddr + rax + 2], r10 mov [sockaddr + 2 + r10], r8b
add rax, 8 add r10, 1
jmp make_sockaddr__copy_server_path jmp make_sockaddr__copy_server_path