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
; Returns:
; rax - non-negative from write(2)
; Errors:
; rax - -1024 - no line was buffered
; rax - other negative - from write(2)
; rax - negative or zero - from write(2)
; Arguments:
; rdi - fd
; rsi - address of client within clients array
; rdx - pollfds index
; Variables:
; rbp - fd
; rbx - pollfds index
; r12 - address of client within clients array
; r13 - line length
; r11 - client buffer end of text after call to write(2)
; r13 - line start
; r14 - line end
; r15 - client buffer end
; r11 - client buffer, length of last incomplete line
client__pollout:
push rbp
push rbx
push r12
push r13
push r14
push r15
mov rbp, rdi
mov rbx, rdx
mov r12, rsi
mov r13, rsi
add r13, OFFSET_CLIENT_BUFFER
mov r15, r13
add r15, 255
push rdi
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 rdi, rbp
mov rsi, r12
add rsi, OFFSET_CLIENT_BUFFER
mov rdx, r13
syscall
call client__pollout__before_fresh_lines
; error from write(2)
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 r11b, [r12 + OFFSET_CLIENT_BUFFER_LEN]
add r11, r12
sub r11, rax
add r11, OFFSET_CLIENT_BUFFER
sub r11, r13
client__pollout__shunt:
client__pollout__shunt__loop:
cmp r10, r11
jge client__pollout__shunt__finished
mov r8b, [r10 + rax]
mov r8b, [r10 + r13]
mov [r10], r8b
add r10, 1
jmp client__pollout__shunt
jmp client__pollout__shunt__loop
client__pollout__shunt__finished:
; buffer_len -= rax
sub [r12 + OFFSET_CLIENT_BUFFER_LEN], al
cmp rax, r13
jl client__pollout__return
mov word [pollfds + rbx * pollfd_size + 4], POLLIN
mov r10, r13
sub r10, r12
sub r10, OFFSET_CLIENT_BUFFER
client__pollout__return:
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
ret
client__pollout__no_line:
mov rax, -1024
jmp client__pollout__return
; Errors:
; rax - -1024 - some scratch buffer bytes remain, stop write(2)ing
; 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
client__shutdown_close:
mov rax, SYS_SHUTDOWN

View file

@ -2,6 +2,7 @@
#include <sys/socket.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
// printf("x %d\n", x);
void main() {
@ -17,4 +18,6 @@ void main() {
printf("POLLERR %d\n", POLLERR);
printf("POLLNVAL %d\n", POLLNVAL);
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
; TODO(?) POLLPRI: see poll(2), tcp(7)
SHUT_RDWR equ 2
EAGAIN equ -11
;STATE_READING equ 0
;STATE_WRITING equ 1
@ -34,14 +35,18 @@ SHUT_RDWR equ 2
OFFSET_CLIENT_FD equ 0
OFFSET_CLIENT_STATE equ 4
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
pollfds_capacity equ 100
client_buffer_size equ 255
; fd, state, buffer_len, buffer
client_size equ 4 + 2 + client_buffer_size
client_scratch_size equ 255
; 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
SECTION .data
@ -158,8 +163,12 @@ _client__pollout:
mov rsi, r12
mov rdx, r15
call client__pollout
cmp rax, EAGAIN
je _client__pollout__finished
cmp rax, 0
jle _client__error_or_eof
_client__pollout__finished:
add r15, 1
jmp scan__loop

View file

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