Compare commits

..
Author SHA1 Message Date
Leency a8f285ec86 kernel/net: lock the socket in the retransmission timer
Check kernel codestyle / Check kernel codestyle (pull_request) Successful in 37s
Test PR / Build (en_US) (pull_request) Successful in 2m47s
Test PR / Build (es_ES) (pull_request) Successful in 2m4s
Test PR / Build (ru_RU) (pull_request) Successful in 1m58s
- take SOCKET.mutex while rewriting SND_NXT/cwnd/ssthresh; skip if an ACK
  stopped or re-armed the timer meanwhile
- back off from t_rxtcur: the first timeout was 3.2 s, the second 25.6 s
2026-09-30 10:14:17 +03:00
Leency 772031e6b6 kernel/net: fix TCP RTT measurement
- tcp_output: the "timing anything?" test was inverted, no segment was timed
- tcp_timer: t_rtt was never incremented
- tcp_xmit_timer: first sample keyed on t_srtt, not t_rtt; signed jg on
  srtt/rttvar updates (ja reset them to 1 whenever RTT dropped); t_rtt = 0
- timestamp RTT: 1/100 s -> 640 ms ticks (RTO came out 64x too long);
  skip it when TSecr is 0
2026-09-30 10:14:15 +03:00
Leency b1110dc03b kernel/net: start persist probes at the retransmission floor
BSD waits 5.12s before the first zero-window probe and doubles from
there. A peer that closes its window and never volunteers an update --
QEMU 0.10's slirp, or any stack applying silly-window avoidance to its
updates -- is rediscovered only by our probe, so 5, 10, 20s of silence
swallowed most of a 15s upload stage. Start at TCP_time_re_min (1.28s),
as Linux starts at the RTO; still exponential, still capped.
2026-09-30 10:14:12 +03:00
Leency 6c30c66aa3 kernel/net: implement the TCP retransmission timeout
t_rxtcur, the timeout the retransmission timer is armed with, was never
assigned anywhere: not at socket creation, not in tcp_xmit_timer. Every
socket armed the timer with 0, the 640 ms tick took it to 0xFFFFFFFF,
and it never expired. And when it did (in principle) expire, the handler
was a bare call tcp_output, which sends from SND_NXT: the unacknowledged
segment before it was never resent, nothing was backed off, the timer
was not re-armed. A segment the peer dropped -- a window that shrank
under data in flight, any loss on the uplink -- stalled the connection
until the application gave up. 23 duplicate ACKs from the peer did not
help either.

Observed as every upload through QEMU's slirp freezing the moment the
host side paused: pcap of an 8 MB POST to a sink that stops reading for
12 s showed the peer's window go 328, the guest's 1400-byte segment
beyond it dropped, then nothing but empty ACKs, and after the window
reopened the guest sent the NEXT 32 KB with the hole still there and
sat. speedtest.net's upload stage lost 3 of 4 connections this way on
the 2009 QEMU.

- tcp_init_socket: t_rxtcur = TCP_time_rtt_default (BSD TCPTV_RTOBASE)
  until the first RTT sample.
- tcp_xmit_timer: t_rxtcur = srtt + 4*rttvar (BSD TCP_REXMTVAL) within
  [re_min, re_max]; a fresh sample resets t_rxtshift.
- tcp_timer, retransmission expiry: BSD TCPT_REXMT -- drop the
  connection with ETIMEDOUT past TCP_max_rxtshift; re-arm with the
  backed-off timeout (shift capped at 6); SND_NXT = SND_UNA; no RTT
  sample from the resent segment; ssthresh = max(2, min(wnd,cwnd)/2/mss)
  segments, cwnd = one segment, dupacks = 0; then tcp_output.

With the patch the same fixture completes: 8 MB, 12.36 s of which 12 s
is the sink's deliberate pause, 205 Mbps once it reads again.
2026-09-30 10:14:12 +03:00
15 changed files with 172 additions and 83 deletions

No files matched your search

-1
View File
@@ -166,7 +166,6 @@ extra_files = {
{"kolibrios/demos/rpento.lif", "common/demos/rpento.lif"},
{"kolibrios/develop/fpc/", "common/develop/fpc/*"},
{"kolibrios/develop/fpc/examples/", "../programs/develop/fp/examples/src/*"},
{"kolibrios/develop/fasm/fasm.txt", SRC_PROGS .. "/develop/fasm/1.73/fasm.txt"},
{"kolibrios/develop/oberon07/compiler.kex", SRC_PROGS .. "/develop/oberon07/Compiler.kex"},
{"kolibrios/develop/oberon07/LICENSE", SRC_PROGS .. "/develop/oberon07/LICENSE"},
{"kolibrios/develop/oberon07/doc/CC.txt", SRC_PROGS .. "/develop/oberon07/doc/CC.txt"},
+5 -5
View File
@@ -20,13 +20,13 @@
<a href="hardware_support.htm">Поддержка оборудования</a>
<strong>Разработка</strong>
<a href="/sys/docpack|d">Справочник по системным функциям Колибри</a>
<a href="/sys/docpack|c">Использование отладчика</a>
<a href="/kolibrios/develop/fasm/fasm.txt">Руководство FASM</a>
<a href="/sys/docpack|f">Справочник по системным функциям Колибри</a>
<a href="/sys/docpack|e">Использование отладчика</a>
<a href="/sys/docpack|d">Руководство FASM</a>
<strong>Использование библиотек</strong>
<a href="/sys/docpack|g">Ini</a>
<a href="/sys/docpack|h">Диалог открытия файла OpenDial</a>
<a href="/sys/docpack|i">Ini</a>
<a href="/sys/docpack|j">Диалог открытия файла OpenDial</a>
<strong>Смотрите также</strong>
Вики проекта <a href="http://wiki.kolibrios.org/">wiki.kolibrios.org</a>
+1 -1
View File
@@ -63,7 +63,7 @@ TCP_OPT_TIMESTAMP = 8
TCP_time_MSL = 47 ; max segment lifetime (30s)
TCP_time_re_min = 2 ; min retransmission (1,28s)
TCP_time_re_max = 100 ; max retransmission (64s)
TCP_time_pers_min = 8 ; min persist (5,12s)
TCP_time_pers_min = 2 ; min persist (1,28s)
TCP_time_pers_max = 94 ; max persist (60,16s)
TCP_time_keep_init = 118 ; connection establishment (75,52s)
TCP_time_keep_idle = 4608 ; idle time before 1st probe (2h)
+6
View File
@@ -525,8 +525,11 @@ endl
test [temp_bits], TCP_BIT_TIMESTAMP
jz .no_timestamp_rtt
cmp [ebx + TCP_SOCKET.ts_ecr], 0 ; nothing echoed
je .no_timestamp_rtt
mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_ecr]
shr eax, 6 ; 1/100 s -> 640 ms ticks
inc eax
call tcp_xmit_timer
jmp .rtt_done
@@ -1114,8 +1117,11 @@ endl
test [temp_bits], TCP_BIT_TIMESTAMP
jz .timestamp_not_present
cmp [ebx + TCP_SOCKET.ts_ecr], 0 ; nothing echoed
je .timestamp_not_present
mov eax, [timestamp]
sub eax, [ebx + TCP_SOCKET.ts_ecr]
shr eax, 6 ; 1/100 s -> 640 ms ticks
inc eax
call tcp_xmit_timer
jmp .rtt_done_
+1 -1
View File
@@ -626,7 +626,7 @@ endl
mov [eax + TCP_SOCKET.SND_MAX], edx ; [eax + TCP_SOCKET.SND_NXT] from before we updated it
cmp [eax + TCP_SOCKET.t_rtt], 0 ; are we currently timing anything?
je @f
jne @f
mov [eax + TCP_SOCKET.t_rtt], 1 ; nope, start transmission timer
mov [eax + TCP_SOCKET.t_rtseq], edi
inc [TCPS_segstimed]
+15 -5
View File
@@ -96,7 +96,7 @@ macro tcp_init_socket socket {
mov [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
mov [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
mov [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
;;; TODO: TCP_time_rangeset
mov [socket + TCP_SOCKET.t_rxtcur], TCP_time_rtt_default
mov [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
mov [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
@@ -518,7 +518,7 @@ tcp_xmit_timer:
inc [TCPS_rttupdated]
cmp [ebx + TCP_SOCKET.t_rtt], 0
cmp [ebx + TCP_SOCKET.t_srtt], 0 ; first sample?
je .no_rtt_yet
; srtt is stored as a fixed point with 3 bits after the binary point.
@@ -534,7 +534,7 @@ tcp_xmit_timer:
pop ecx
add [ebx + TCP_SOCKET.t_srtt], eax
ja @f
jg @f ; signed: delta may be negative
mov [ebx + TCP_SOCKET.t_srtt], 1
@@:
@@ -556,10 +556,10 @@ tcp_xmit_timer:
pop edx
add [ebx + TCP_SOCKET.t_rttvar], eax
ja @f
jg @f
mov [ebx + TCP_SOCKET.t_rttvar], 1
@@:
ret
jmp .rto
.no_rtt_yet:
@@ -572,6 +572,16 @@ tcp_xmit_timer:
mov [ebx + TCP_SOCKET.t_rttvar], eax
pop ecx
.rto:
; Retransmit timeout = srtt + 4*rttvar, reset the backoff
push ecx
mov ecx, [ebx + TCP_SOCKET.t_srtt]
shr ecx, TCP_RTT_SHIFT
add ecx, [ebx + TCP_SOCKET.t_rttvar]
tcpt_rangeset [ebx + TCP_SOCKET.t_rxtcur], ecx, TCP_time_re_min, TCP_time_re_max
pop ecx
mov [ebx + TCP_SOCKET.t_rxtshift], 0
mov [ebx + TCP_SOCKET.t_rtt], 0 ; the timed segment is done
ret
+93
View File
@@ -91,6 +91,10 @@ proc tcp_timer_640ms
jne .loop
inc [eax + TCP_SOCKET.t_idle]
cmp [eax + TCP_SOCKET.t_rtt], 0 ; timing a segment?
je @f
inc [eax + TCP_SOCKET.t_rtt]
@@:
test [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
jz .check_more2
@@ -99,6 +103,95 @@ proc tcp_timer_640ms
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Retransmission timer expired\n", eax
; Lock socket, an ACK may have stopped or restarted the timer meanwhile
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_lock
popa
test [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
jz .rexmt_cancelled
cmp [eax + TCP_SOCKET.timer_retransmission], 0
jne .rexmt_cancelled
; Too many retransmissions? Drop the connection
inc [eax + TCP_SOCKET.t_rxtshift]
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
jbe .rexmt
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: too many retransmissions, dropping\n", eax
push [eax + SOCKET.NextPtr]
mov ebx, ETIMEDOUT
call tcp_drop
pop eax
jmp .check_only
.rexmt_cancelled:
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
jmp .check_more2
.rexmt:
push ebx ecx edx
; Restart timer with backoff: t_rxtcur << min(t_rxtshift, 6)
mov ebx, [eax + TCP_SOCKET.t_rxtcur]
mov cl, [eax + TCP_SOCKET.t_rxtshift]
cmp cl, 6
jbe @f
mov cl, 6
@@:
shl ebx, cl
cmp ebx, TCP_time_re_min
jae @f
mov ebx, TCP_time_re_min
@@:
cmp ebx, TCP_time_re_max
jbe @f
mov ebx, TCP_time_re_max
@@:
mov [eax + TCP_SOCKET.timer_retransmission], ebx
; Resend from the last acknowledged byte, don't time it
push [eax + TCP_SOCKET.SND_UNA]
pop [eax + TCP_SOCKET.SND_NXT]
mov [eax + TCP_SOCKET.t_rtt], 0
mov [eax + TCP_SOCKET.t_dupacks], 0
; Slow start: ssthresh = max(2, min(wnd, cwnd) / 2 / mss) * mss, cwnd = mss
mov ecx, [eax + TCP_SOCKET.t_maxseg]
mov edx, [eax + TCP_SOCKET.SND_WND]
cmp edx, [eax + TCP_SOCKET.SND_CWND]
jbe @f
mov edx, [eax + TCP_SOCKET.SND_CWND]
@@:
mov ebx, eax ; socket ptr
mov eax, edx
shr eax, 1
xor edx, edx
div ecx
cmp eax, 2
jae @f
mov eax, 2
@@:
mul ecx
mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax
mov [ebx + TCP_SOCKET.SND_CWND], ecx
mov eax, ebx
pop edx ecx ebx
pusha
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
popa
push eax
call tcp_output
pop eax
+2 -7
View File
@@ -31,7 +31,6 @@ macro debug_print_dec arg
dpd fix debug_print_dec
;---------------------------------
if used debug_outdec
debug_outdec: ;(eax - num, edi-str)
push 10 ;2
pop ecx ;1
@@ -60,9 +59,7 @@ debug_outchar: ; al - char
popad
popf
ret
end if
if used debug_outstr
debug_outstr:
mov eax,63
mov ebx,1
@@ -75,7 +72,7 @@ debug_outstr:
jmp @b
@@:
ret
end if
macro newline
{
@@ -115,7 +112,6 @@ macro debug_print_hex arg
}
dph fix debug_print_hex
if used debug_outhex
debug_outhex:
; eax - number
mov edx, 8
@@ -134,5 +130,4 @@ debug_outhex:
ret
__hexdigits:
db '0123456789ABCDEF'
end if
db '0123456789ABCDEF'
+3 -12
View File
@@ -104,12 +104,8 @@ START:
load_libraries l_libs_start,end_l_libs
cmp [lib1.status_lib],0
jnz close
cmp [lib2.status_lib],0
jnz close
cmp [lib4.status_lib],0
jnz close
cmp eax,-1
jz close
mcall SF_SET_EVENTS_MASK,0x80000067 ; 1100111b
;---------------------------------------------------------
@@ -226,14 +222,9 @@ include 'menu.inc'
;-----------------------------------------------------------
;------------variables and data of program------------------
;-----------------------------------------------------------
name_of_program db 'ANIMAGE graphics editor v1.54',0
mouse_pos_x db 'X='
mouse_pos_y db 'Y='
new_text1 db 'Picture size X'
new_text2 db 'Picture size Y'
ok_text db 'OK'
include 'lib_data.inc'
include 'panel_data.inc'
include 'brushes.inc'
include 'spray.inc'
include 'width_lines.inc'
@@ -3,23 +3,8 @@
;---------------------------------------------
align 4
mouse:
cmp [lib3.status_lib],0 ; test load library
jnz .m_end
cld
stdcall [kmainmenu_dispatch_cursorevent], [main_menu]
mov eax,[main_menu]
cmp dword[eax+16],-1
je @f
mov [m_lost],1
jmp still
@@:
cmp [m_lost],0
je .m_end
dec [m_lost]
jmp still
.m_end:
or ecx,-1
mcall SF_THREAD_INFO,procinfo
+24 -19
View File
@@ -1,13 +1,15 @@
align 4
square_width_put:
macro square_width_put
{
local .no_put_to_screen
local .next_color_put
local .vertical_width_put
local .horizontal_width_put
mov ebx,[ReserveArray]
mov eax,[ebx]
test eax,eax
jz .no_put_to_screen
mov ecx,[ebx]
cmp ecx,[Picture_SizeX]
jg .no_put_to_screen ;if ecx > screen size return
add ebx,4
xor ebp,ebp
@@ -46,10 +48,13 @@ square_width_put:
jnz .next_color_put
.no_put_to_screen:
ret
}
align 4
square_width_save:
macro square_width_save
{
local .next_color_save
local .vertical_width_save
local .horizontal_width_save
mov ebx,[ReserveArray]
mov [ebx],eax
mov ecx,eax
@@ -88,7 +93,7 @@ square_width_save:
add ebx,4
dec ecx
jnz .next_color_save
ret
}
macro draw_calc_pixels brush
{
@@ -675,7 +680,7 @@ TakeButtonInstruments:
no_new_line_xy:
;put saved pixels
call square_width_put
square_width_put
;calculate line
mov ebx,[ReserveArray]
@@ -707,7 +712,7 @@ TakeButtonInstruments:
call calculate_line
;save color pixels in ReserveArray
call square_width_save
square_width_save
;draw calculated pixels on work arrea
draw_calc_pixels width_pixels
@@ -741,7 +746,7 @@ TakeButtonInstruments:
no_new_rectangle_xy:
;put saved pixels
call square_width_put
square_width_put
;calculate line
mov ebx,[ReserveArray]
@@ -773,7 +778,7 @@ TakeButtonInstruments:
call calculate_rectangle
;save color pixels in ReserveArray
call square_width_save
square_width_save
;draw calculated pixels on work arrea
draw_calc_pixels width_pixels_rectangle
@@ -807,7 +812,7 @@ TakeButtonInstruments:
no_new_circle_xy:
;put saved pixels
call square_width_put
square_width_put
mov esi,[ScreenX]
mov edi,[ScreenY]
@@ -926,7 +931,7 @@ TakeButtonInstruments:
call calculate_circle
;save color pixels in ReserveArray
call square_width_save
square_width_save
;draw calculated pixels on work arrea
draw_calc_pixels width_pixels
@@ -1306,7 +1311,7 @@ end if
no_new_konture_xy:
;put saved pixels
call square_width_put
square_width_put
;calculate line
mov ebx,[ReserveArray]
@@ -1338,7 +1343,7 @@ end if
call calculate_line
;save color pixels in ReserveArray
call square_width_save
square_width_save
;draw calculated pixels on work arrea
draw_calc_pixels width_pixels
@@ -1379,7 +1384,7 @@ end if
no_new_ellips_xy:
;put saved pixels
call square_width_put
square_width_put
mov esi,[ScreenX]
@@ -1490,7 +1495,7 @@ end if
call calculate_ellips
;save color pixels in ReserveArray
call square_width_save
square_width_save
;draw calculated pixels on work arrea
draw_calc_pixels width_pixels
-8
View File
@@ -15,8 +15,6 @@ no_set:
}
init_main_menu:
cmp [lib3.status_lib],0 ; test load library
jnz @f
stdcall [kmenu_init], syscolors
stdcall [ksubmenu_new]
@@ -112,14 +110,10 @@ init_main_menu:
; add 'Reflection' menu to main
stdcall [kmenuitem_new], KMENUITEM_SUBMENU, sz_main_menu_Filters, [main_menu_filters]
stdcall [ksubmenu_add], [main_menu], eax
@@:
ret
put_main_menu:
cmp [lib3.status_lib],0 ; test load library
jnz @f
stdcall [kmainmenu_draw], [main_menu]
@@:
ret
button_handler_main_menu:
@@ -151,13 +145,11 @@ button_handler_main_menu:
.end_handler:
ret
align 4
main_menu dd 0
main_menu_file dd 0
main_menu_edit dd 0
main_menu_instr dd 0
main_menu_filters dd 0
m_lost db 0
sz_main_menu_File db 'File', 0
sz_main_menu_File_New db 'New', 0
+9
View File
@@ -0,0 +1,9 @@
;**********************************************************
;------------------TEXT DATA-------------------------------
;**********************************************************
name_of_program db 'ANIMAGE graphics editor v1.53',0
mouse_pos_x db 'X='
mouse_pos_y db 'Y='
new_text1 db 'PICTURE SIZE X'
new_text2 db 'PICTURE SIZE Y'
ok_text db 'OK'
+3
View File
@@ -15,6 +15,9 @@ then tup.append_table(deps,
else tup.append_table(deps,
tup.rule("../../../kernel/trunk/docs/sysfuncs.txt", cp_cmd, "SysFuncs.txt"))
end
tup.append_table(deps,
tup.rule("../../develop/fasm/1.73/fasm.txt", cp_cmd, "Fasm.txt")
)
tup.append_table(deps,
tup.rule("../../../kernel/trunk/docs/stack.txt", cp_cmd, "Stack.txt")
)
+10 -9
View File
@@ -9,7 +9,7 @@
;---------------------------------------------------------------------
FILE_COUNT=0
DEF_FILE equ 'f'
DEF_FILE equ 'g'
macro embed_docdir_file fn
{
@@ -197,17 +197,18 @@ embedded:
embed_docdir_file 'Copying.txt' ;a
embed_docdir_file 'Hot_Keys.txt' ;b
embed_docdir_file 'Mtdbg.txt' ;c
embed_local_file 'Fasm.txt' ;c
embed_docdir_file 'Mtdbg.txt' ;d
if lang eq ru_RU
embed_local_file 'SysFuncr.txt' ;d
embed_local_file 'SysFuncr.txt' ;e
else ; Default to en_US
embed_local_file 'SysFuncs.txt' ;d
embed_local_file 'SysFuncs.txt' ;e
end if
embed_local_file 'Stack.txt' ;e
embed_docdir_file 'KFAR_Keys.txt' ;f
embed_docdir_file 'INI.txt' ;g
embed_docdir_file 'OpenDial.txt' ;h
embed_docdir_file 'Credits.txt' ;i
embed_local_file 'Stack.txt' ;f
embed_docdir_file 'KFAR_Keys.txt' ;g
embed_docdir_file 'INI.txt' ;h
embed_docdir_file 'OpenDial.txt' ;i
embed_docdir_file 'Credits.txt' ;j
; -- End of embedding area -------
dd 0