libc/crt0: возврат из main завершает программу по-настоящему

Два бага одного пути завершения, оба видны только на железе.

1. ЗВУК ПРОДОЛЖАЛСЯ ПОСЛЕ ВЫХОДА.  cbl_close() закрывает СЕССИЮ, но не
гасит железо: bit7 порта 0x004E держит gfx_wait_vsync ради бита луча,
поэтому порт оставался включённым ("немой" режим), и CBL крутил свои 256
слотов уже под шеллом — тихо ровно до первой чужой записи в порт данных,
а дальше она зацикливалась.  Новый cbl_shutdown() гасит bit7 независимо
от держателей и центрует ЦАП обычного COVOX; pop_shutdown зовёт его
последним действием, а _cbl_open_raw регистрирует в atexit его, а не
cbl_close.

2. ЦЕПОЧКА atexit НЕ ВЫПОЛНЯЛАСЬ ПРИ ВОЗВРАТЕ ИЗ main.  crt0 уходил прямо
в ESTEX EXIT, то есть нарушал контракт C (возврат из main = exit(status)).
Молча терялись не только гашение звука и снятие vsync-ссылки, но и
_fclosall: буферизованная запись в файлы пропадала, если программа не
звала exit() явно.  Теперь crt0 после main дёргает _atexit_hook.

Косвенность обязательна: прямая ссылка crt0 на разматыватель притащила бы
его и стек хендлеров в КАЖДУЮ программу.  Указатель живёт в отдельном
data-модуле (два байта _DATA, ни байта кода), ставит его сам atexit() при
первой регистрации — нет регистраций, нет и кода.  Тот же приём, что у
_irq_cbl_hook.

Цена замерена: +14 Б всем программам (блок в crt0) и +64 Б тем
одиннадцати, что реально регистрируют хендлеры (CBL, файловые через
_fclosall, irqtest, gfx_dbuf, solidt) — у них раньше эти хендлеры были
мёртвым кодом.  Эталоны обновлены (кроме atlas: его +434 Б не отсюда,
замерен тот же и без этих правок).

Проверено в MAME: старт и звук как были, выход по F10 возвращает в шелл
чисто (текстовый режим восстановлен, зависания нет), повторный запуск
работает.  Пункт 1 проверяется только на железе.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DSYUpuaQpKr48kBav2iiV4
This commit is contained in:
2026-09-02 14:15:48 +03:00
parent 31d0075090
commit 8490288d79
12 changed files with 203 additions and 58 deletions
+45 -45
View File
@@ -1,67 +1,67 @@
# Эталон размеров _CODE (байт); обновление: python3 toolchain/size_check.py --update
accfill 3783
accfill 3797
accop 7067
argv 3431
assrtest 3847
argv 3445
assrtest 3861
atlas 9193
attrprob 4087
banked 1056
bankedbg 1067
banklocl 4683
banktest 3767
bgi_img 8677
bgitest 3748
bios_text 4461
attrprob 4101
banked 1070
bankedbg 1081
banklocl 4697
banktest 3781
bgi_img 8691
bgitest 3762
bios_text 4475
blitperf 5860
blitw 4939
cat 913
cblstream 5862
cbltest 6008
cblwav 6101
conio 4605
conio2 3929
cat 927
cblstream 5944
cbltest 6090
cblwav 6183
conio 4619
conio2 3943
convbench 3508
dec_test 860
errno 5966
fbench 8085
fdmax 6023
filetest 10547
dec_test 874
errno 5980
fbench 8149
fdmax 6087
filetest 10611
fpsdiv 4870
gets 509
gfx_dbuf 5142
gfx_demo 4114
gets 523
gfx_dbuf 5207
gfx_demo 4128
gfxbanks 6044
hello 4167
hello2 4244
irqtest 6690
hello 4181
hello2 4258
irqtest 6754
kbdpoll 1282
kbdraw 4911
ls 4835
malloc 4461
mem_test 4555
mouse 4382
openenv 6124
ls 4849
malloc 4475
mem_test 4569
mouse 4396
openenv 6138
pageflip 6334
palfile 5406
ptime 5744
rt_test 5197
ptime 5758
rt_test 5216
scroll 6744
seek 4188
simple 955
solidt 11531
seek 4202
simple 969
solidt 11595
spranim 9431
spriteclip 4119
sprites 6791
stattest 7549
stdlib 6643
stest2 3644
strtest 1340
text_palette 5024
timedir 5454
stattest 7563
stdlib 6657
stest2 3658
strtest 1354
text_palette 5038
timedir 5468
w0page 8831
w3bgfx 5243
w3big 3673
w3huge 3700
w3probe 3556
w3tiny 3471
winrest 4459
winrest 4473
1 # Эталон размеров _CODE (байт); обновление: python3 toolchain/size_check.py --update
2 accfill
3 accop
4 argv
5 assrtest
6 atlas
7 attrprob
8 banked
9 bankedbg
10 banklocl
11 banktest
12 bgi_img
13 bgitest
14 bios_text
15 blitperf
16 blitw
17 cat
18 cblstream
19 cbltest
20 cblwav
21 conio
22 conio2
23 convbench
24 dec_test
25 errno
26 fbench
27 fdmax
28 filetest
29 fpsdiv
30 gets
31 gfx_dbuf
32 gfx_demo
33 gfxbanks
34 hello
35 hello2
36 irqtest
37 kbdpoll
38 kbdraw
39 ls
40 malloc
41 mem_test
42 mouse
43 openenv
44 pageflip
45 palfile
46 ptime
47 rt_test
48 scroll
49 seek
50 simple
51 solidt
52 spranim
53 spriteclip
54 sprites
55 stattest
56 stdlib
57 stest2
58 strtest
59 text_palette
60 timedir
61 w0page
62 w3bgfx
63 w3big
64 w3huge
65 w3probe
66 w3tiny
67 winrest