GELİŞTİRME GÜNLÜĞÜ
M3 — Scheduler
M3
Task + Context Switch + CFS-lite + Soft Preemption
19 Mayıs 2026 • 5 alt adım + 7 bug fix sonrası çalıştı
3 TASK INTERLEAVE
✓ M3.1
Task + TaskContext
x19–x30 + SP + FpState (q0–q31 + fpsr + fpcr)
✓ M3.2
context_switch.S
AAPCS64 callee-saved + FP/SIMD save/restore
✓ M3.3
Scheduler + BinaryHeap
CFS-lite weight, aging, normalization
✓ M3.4
Soft preemption
NEED_RESCHED + check_resched()✓ M3.5
3 task demo
HIGH/MED/LOW prio 0/2/5, slice 2/3/4
Bug-discovery hikayesi (7 fix)
İlk çalıştırmada sadece LOW task basıyordu, min_vruntime sürekli 0'da kilitliydi. 7 bug bulduk:
BinaryHeap max-heap (en yüksek vr pop oluyordu),recalculate_min_vruntime candidate=0 başlangıcı, IRQ handler'dan context_switch (trap frame korrupsiyonu),yield_now irq_lock yok,task_exit_trampoline zombie task,CPACR_EL1.FPEN kapalı (FP trap riski), duplicate effective_vruntime.QEMU çıktısı (4 sn)
[Scheduler] Task #1 'High-Prio' spawn [Scheduler] Task #2 'Medium-Prio' spawn [Scheduler] Task #3 'Low-Prio' spawn [HIGH ] prio=0 | vr=0 | eff= 0 | min=0 [MED ] prio=2 | vr=0 | eff= 2 | min=0 [LOW ] prio=5 | vr=0 | eff=12 | min=0 ... (interleave devam ediyor) 4-saniye toplam: HIGH : 14 865 satır MED : 28 563 satır LOW : 7 497 satır min_vruntime : 0 → 306 → 591 (artıyor)
Bilinçli erteleme:Gerçek IRQ-driven preemption (timer IRQ → doğrudan context_switch) bu adımda YOK. Yerine "soft preemption" pattern'i: timer tick
NEED_RESCHED bayrağı set ediyor, task'ler check_resched() ile bayrağı işliyor. Exception trampoline'in trap-frame layout'u TaskContext'le hizalı değil — gerçek preemption için ikisini birleştirmek gerekiyor (M3.4-real).AUDIT
M1 + M2 + M3 Audit — 13 bug fix
19 Mayıs 2026 • Sistematik kod review + compile-time guard'lar
3 KRİTİK · 7 ORTA · 3 KÜÇÜK
🔴 KRİTİK — Silent corruption / leak
#1 TaskContext fp offset 104 vs 112
FpState
align(16) → Rust int kısmından sonra 8 byte padding ekler. Asm #104 diyordu → q0/q1 padding'e yazılıyor, tüm q-registerlar 8 byte kayık. Demo FP kullanmıyor, patlamıyordu — silent corruption bekliyordu.Fix: asm
#104 → #112 + Rust'taconst _: () = assert!(offset_of!(TaskContext, fp) == 112);#2 TCR_EL1.SH0 yanlış bit pozisyonu
SH0
(0b10 << 8) ile yazılıyordu — ARM ARM'a göre SH0 bits[13:12], << 8 IRGN0 alanı. OR'lanınca SH0 = Non-shareable kaldı. SMP'de cache coherency hazardı.Fix:
(0b11 << 12). Doğrulama: TCR_EL1 0x800710 → 0x803510.#3 Dead task scheduler'dan çıkmıyor
task_exit() Dead set + loop yield_now. yield_now Dead task'i queue'ya geri push ediyordu → sonsuz pop+push+context_switch döngüsü → CPU sızıntısı.Fix: yield_now içinde
state == Dead → push ETME, Box drop.🟡 ORTA — Yapısal / sürdürülebilirlik
#4 INNER_SHAREABLE pattern
İsim/değer ters:
0b10 Outer, 0b11 Inner.#5 enable_fp_access duplicate
main.rs çağrıyı 2 kez yapıyordu.
#6 flags() lower 32 bit kaybı
Yanlış mask → VALID/AP/SH/AF okunmuyordu.
#7-#8 Ölü kod
schedule() / enable_mmu_with_barriers() → #[allow(dead_code)]#9 GIC priority reset
256 IPRIORITYR 0xff ile init.
#10 GICC_BPR set
Binary point register açıkça 0.
#13 unreachable!()
start_first_task ölü loop semantic hata → unreachable!().🟢 KÜÇÜK + Dokümante TODO'lar
#14 size_of::<PageTable>()
dcache flush hardcoded 4096 → compile-time size.
#15 PhysFrame::prev
wrapping_neg → düz çıkarma.#16 Stale doc-comments
Modül başlıkları güncel akışla yenilendi.
#11 NORMAL W+X → TODO M5
.text=RX / .data=RW+UXN+PXN.
#12 TaskContext eksik → TODO M3.4-real
ELR_EL1, SPSR_EL1, x0–x18 eklenmeli.
#18-#19 Stack guard / IRQ stack → M5 / M3.4-real
VMM ile guard page + per-CPU IRQ stack.
Compile-time koruma eklendi
const _: () = { assert!(offset_of!(TaskContext, fp) == 112); assert!(size_of::<FpState>() == 528); };Gelecekte birinin TaskContext'e field eklemesi veya FpState alignment'ını değiştirmesi durumunda build derleme hatası verir — silent FP korupsiyonu yerine. Audit'in en değerli tek satırı.
Commits:
6295b97 (M3 first 7 fix) · 54719fb (audit 3 critical + 5 cleanup) ·5de7fe2 (remaining 7 yellow/green fix)M3.4-real
Gerçek IRQ-driven Preemption
19 Mayıs 2026 • büyük refactor BEKLENMİYORDU — 3 küçük fix yetti
PURE-COMPUTE TASK'LER PREEMPT EDİLİYOR
Audit'in bug #3'ü ("IRQ handler içinden context_switch yapma") fazla paranoyaktı: aslında çalışıyor. Her task'in kendi kernel stack'i geçerli bir unwind point taşır — ya bir yield_now sonrası ya da bir IRQ trampoline'ın
bl rust_irq_handler sonrası. context_switch yeni task'i o noktalardan birine indirir. Asıl problem 3 küçük şeydi:3 küçük ama sinsi bug
A. SP 8-aligned (16 olmalı)
TaskContext::new sp = stack_top & !0xF; sp -= 8;yapıyordu → AAPCS64 SP 16-aligned şartını ihlal. C ilk STP'de EC=0x26 SP align fault. Hiç fark edilmemişti çünkü C'ye hiç ulaşamıyorduk.Fix:
sp -= 8 kaldırıldı (task -> !, return chain gerek değil).B. DAIF.I IRQ'tan miras kalıyor
ret PSTATE.DAIF'i restore ETMEZ. context_switch IRQ handler içinden çağrıldığında yeni task DAIF.I=1 (mask) ile başlıyor → bir daha asla timer IRQ ALMIYOR → tek switch sonra sonsuza kadar tek task.Fix: context_switch.S sonunda
msr daifclr, #2 ekledim (kernel task'leri hep IRQ açık çalışır).C. EOI yazılmadan preempt
rust_irq_handler: scheduler_tick → yield_now → context_switch → yeni task →asla geri dönmüyor → trailing gic::end_of_interrupt çalışmıyor → GIC timer IRQ'yu hâlâ "active" görüyor, yeni tick'i iletmiyor.Fix: EOI preempt'ten ÖNCE yazıldı. Preempt başarısız olsa bile GIC temiz kalır.
Demo değişikliği
3 task de aynı priority + pure compute:
yield_now yok, check_resched yok, sadece loop { kprintln!("[X] iter={}", i); i+=1; }. Timer IRQ tek başına preempt etmek zorunda.QEMU çıktısı (4 sn)
A : 87 095 B : 90 325 ← ~%33 her biri, EŞIT round-robin C : 87 073 [A] iter=0 ... iter=1071 (slice ~1100) [B] iter=0 ... iter=1272 (slice ~1300) [C] iter=0 ... iter=1199 (slice ~1200) [A] iter=1072 ... iter=2297 (sonraki tur) [B] iter=1273 ... iter=2512 [C] iter=1200 ... iter=2388 ... (toplam ~70 tur, 4 sn'de)
Sonuç:"Büyük refactor" diye tasarlanan M3.4-real aslında 3 satırlık 3 fix oldu (SP, DAIF, EOI sırası). Audit aşamasındaki bug #3 endişesi olmasaydı (NEED_RESCHED bayrak yaklaşımı) bu çok daha erken ortaya çıkardı — ama M3.4-real'in başarısı yine de audit'in "compile-time guard'ı" olmadan imkansız olurdu (offset_of! TaskContext layout'unu garanti ediyor). Commit:
2b4a910.