{ "$schema": "../../../tools/card-layouts/schemas/card-source.schema.json", "schema": "esc-card-source.v1", "card": { "id": "mpabi-freertos-c-04-delay-state", "series": "freertos-c", "series_title": "FreeRTOS C", "number": "04", "count": "15", "slug": "delay-state", "title": "Delay, blokowanie, stany taska i usuwanie", "topic": "vTaskDelayUntil, Blocked, Suspended i vTaskDelete", "project": "Freestanding C nad FreeRTOS", "subject": "Informatyka", "level": "Rok 2 · L04 · RV32I/Hazard3", "revision_date": "2026-07-19T00:00:00+02:00", "status": "Gotowa", "version": "v00.01", "uuid": "7691d61c-eaae-5228-b9c8-fa42527b75b9", "author": "M. Pabiszczak", "year": "2026" }, "generated": { "tex": "doc/generated/main.tex", "html": "web/index.html", "html_css": "web/style.css", "html_tree_inspector": false, "react_app": true }, "render_dictionary": false, "viewpoints": [ { "id": "A1", "label": "CONTEXT", "subtitle": "Granice systemu", "status": "unavailable", "reason": "Granica aplikacja–kernel–Hazard3 nie zmienia się względem FC03." }, { "id": "A2", "label": "STRUCTURE", "subtitle": "Konteksty i oś wybudzeń", "status": "enabled", "target_label": "fig:a2-structure" }, { "id": "A3", "label": "DISPATCH", "subtitle": "Callback ABI", "status": "unavailable", "reason": "TaskFunction_t i void* zostały udowodnione w FC02." }, { "id": "A4", "label": "APPLICATION", "subtitle": "Topologia", "status": "unavailable", "reason": "Topologia trzech tasków jest już kompletna w A2 i A5." }, { "id": "A5", "label": "FLOW", "subtitle": "E01–E10 od startu do PASS", "status": "enabled", "target_label": "fig:a5-flow" }, { "id": "A6", "label": "STATE", "subtitle": "Ready, Running, Blocked, Suspended, Deleted", "status": "enabled", "target_label": "fig:a6-state" }, { "id": "A7", "label": "RUNTIME", "subtitle": "eTaskState, TCB, stack i tick", "status": "enabled", "target_label": "fig:a7-runtime" }, { "id": "A8", "label": "PATTERNS", "subtitle": "Wzorce", "status": "unavailable", "reason": "Karta bada semantykę stanu kernela, nie wzorzec aplikacyjny." } ], "debug_strategies": { "code.state-model": { "id": "code.state-model", "kind": "code", "action": "open", "expected_observations": [ "stan aplikacyjny i eTaskState są osobnymi pojęciami", "context pozostaje po self-delete" ], "assertions": [ "Blocked ma warunek wybudzenia", "Suspended nie ma automatycznego wake tick" ], "evidence_fields": [ "code_ref", "typ pola", "kotwica UML" ], "prerequisites": [ "źródło FC04" ], "layout": [ "nagłówek kontekstów", "kod tasków", "diagram stanu" ], "commands": [ "rg -n 'PeriodicContext|SuspendContext|eTaskState|Fc04Phase' include src" ] }, "run.state": { "id": "run.state", "kind": "run", "action": "replay", "expected_observations": [ "observer widzi eBlocked i eSuspended", "resume wybiera wyższy task" ], "assertions": [ "publiczne handle są ważne podczas obserwacji", "każdy task czyści własny handle" ], "evidence_fields": [ "event_id", "state", "handle", "PC", "SP", "timestamp" ], "prerequisites": [ "Hazard3 online", "czysta RAM" ], "layout": [ "source", "eTaskState", "handle/TCB", "PC/SP" ], "commands": [ "print g_periodic", "print g_suspend_target", "print g_observer" ] }, "run.timeline": { "id": "run.timeline", "kind": "run", "action": "replay", "expected_observations": [ "kolejne delty wynoszą dokładnie 2", "task jest Blocked między wybudzeniami" ], "assertions": [ "release count=3", "SP mieści się w stack range" ], "evidence_fields": [ "initial tick", "release ticks", "SP", "stack range" ], "prerequisites": [ "scheduler uruchomiony", "period=2" ], "layout": [ "vTaskDelayUntil call", "wake ticks", "task stack" ], "commands": [ "print g_periodic.initial_tick", "print g_periodic.release_tick", "print g_periodic.release_count" ] }, "run.pass": { "id": "run.pass", "kind": "run", "action": "replay", "expected_observations": [ "timeline 2/4/6", "resumed=1", "PASS=1" ], "assertions": [ "observer uruchamia się po wyższych taskach", "forensic context nie jest dereferencją usuniętego TCB" ], "evidence_fields": [ "PASS", "timeline", "source blob", "image hash", "timestamp" ], "prerequisites": [ "oba taski robocze zakończone" ], "layout": [ "contexts", "timeline", "final assertions" ], "commands": [ "print g_fc04_pass", "print g_periodic", "print g_suspend_target" ] } }, "template": "templates/karta-klasyczna.json", "title_block": { "category": "KARTA PRACY · INFORMATYKA", "prepared_by": "M. Pabiszczak", "prepared_on": "2026-07-19T00:00:00+02:00", "title": "Delay, blokowanie, stany taska i usuwanie", "url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/4a7ef04c-ab08-5783-9192-5b02a90f05f8", "repository_url": "https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-c-delay-state", "url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84", "url_domain": "mpabi.pl", "doc_uuid": "4a7ef04c-ab08-5783-9192-5b02a90f05f8", "revision": "v00.01", "issued_on": "2026-07-19T00:00:00+02:00", "series": "FREERTOS-C-04", "document_type": "karta pracy", "tool": "card-layouts", "show_qr": true, "show_repository_qr": true, "height_cm": 2.6, "repeat_on_every_page": true, "replace_front_matter": true }, "front_page_scope": { "title": "Cel karty", "content_tex": "Uczeń odróżnia Ready, Running, Blocked, Suspended i Deleted oraz wiąże każdy stan z konkretną przyczyną i publiczną obserwacją FreeRTOS.", "scope_title": "Zakres karty", "scope_content_tex": "Task okresowy budzi się co dwa ticki przez vTaskDelayUntil. Drugi task zawiesza się bez warunku czasowego i jest jawnie wznawiany. Observer sprawdza publiczne eTaskState, dokładną oś 2/4/6, osobny stos i bezpieczny zapis przed self-delete.", "scope_table": { "headers": [ "Lekcja", "Task", "Najważniejsza idea", "Priorytet", "Status", "Version" ], "rows": [ { "chapter": "FC04", "task": "Task01", "idea_tex": "vTaskDelayUntil, Blocked, Suspended i vTaskDelete", "priority": "główny", "status": "ready", "version": "v00.01", "key": true } ] } }, "side_margin_tree_layout": { "columns": [ { "id": "zawodowe", "label": "TECH", "side": "left", "tree": "WE -> EK -> KW", "description": "Dowody runtime." }, { "id": "ogolne", "label": "OG", "side": "right", "tree": "WE -> EN -> KW", "description": "Model FreeRTOS C." } ] }, "learning_effects": { "FC04.EN01": { "bloom_level": "Analiza", "label": "Model stanów taska", "text": "Uczeń rozróżnia Ready, Running, Blocked, Suspended i Deleted oraz przyczynę każdego przejścia.", "assessment_criteria": [ "FC04.KW01" ] }, "FC04.EK01": { "bloom_level": "Zastosowanie", "label": "Replay delay i resume", "text": "Uczeń odtwarza E01–E10 i wiąże publiczny stan, tick, PC/SP, TCB oraz stos.", "assessment_criteria": [ "FC04.KW01" ] } }, "assessment_criteria": { "FC04.KW01": { "text": "Program kończy się PASS; observer widzi eBlocked i eSuspended; timeline ma dokładne delty 2; resume działa raz; context, TCB i stack pozostają rozdzielone.", "learning_effects": [ "FC04.EN01", "FC04.EK01" ] } }, "educational_requirements": { "FC04.WE01": { "text": "Zaprojektowanie i zbadanie deterministycznego eksperymentu delay, suspend, resume i self-delete.", "label": "vTaskDelayUntil, Blocked, Suspended i vTaskDelete", "learning_effects": [ "FC04.EN01", "FC04.EK01" ], "learning_tree": { "schema": "we-learning-tree.v1", "policy": "Każda aktywna kotwica wskazuje kod lub checkpoint.", "ogolne": [ { "effect_ref": "FC04.EN01", "display": "EN LOCAL RTOS.04", "source": "LOCAL", "official": "RTOS", "local": "04", "kind": "EN", "tree_id": "FC04.WE01.OG.LOCAL.RTOS.04", "text": "Uczeń rozróżnia Ready, Running, Blocked, Suspended i Deleted oraz przyczynę każdego przejścia.", "kw": [ { "criterion_ref": "FC04.KW01", "display": "KW LOCAL RTOS.04", "source": "LOCAL", "kind": "KW", "official": "RTOS", "local": "04", "text": "Łączy kod, diagram i zweryfikowany dowód." } ] } ], "zawodowe": [ { "effect_ref": "FC04.EK01", "display": "EK LOCAL RTOS.04", "source": "LOCAL", "official": "RTOS", "local": "04", "kind": "EK", "tree_id": "FC04.WE01.TECH.LOCAL.RTOS.04", "text": "Uczeń odtwarza E01–E10 i wiąże publiczny stan, tick, PC/SP, TCB oraz stos.", "kw": [ { "criterion_ref": "FC04.KW01", "display": "KW LOCAL RTOS.04", "source": "LOCAL", "kind": "KW", "official": "RTOS", "local": "04", "text": "Łączy kod, diagram i zweryfikowany dowód." } ] } ] } } }, "debug_checkpoints": { "schema": "stem-debug-checkpoints.v1", "semantics": "deterministic-replay", "artifact": { "source": "src/tasks/task01_delay_state.c", "source_git_blob": "0a1cbe0370664498693cefb30c22112b9a7ceae6", "elf": "build/task01_delay_state/prog.elf", "hazard3_elf_sha256": "14ca6067a49ed05baa8f545a4694e1f6e4c722d9cac06c316d116caf761ef4f6", "hazard3_image": "build/task01_delay_state/prog.bin", "hazard3_image_sha256": "9e7091e3ba1389bbc2e2d92b7f87ee1add277c284297df1b62c074410bca16f6" }, "targets": { "hazard3-sim": { "adapter": "hazard3-reset-load-replay.v1", "baseline": "restart-backend", "clean_ram": true } }, "items": { "task01.config": { "event_id": "E01", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 1" }, "verify": { "expressions": [ { "expr": "g_fc04_last_checkpoint", "equals": 1 }, { "expr": "g_periodic.handle == 0", "equals": 1 } ] } }, "task01.scheduler": { "event_id": "E02", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 2" }, "verify": { "expressions": [ { "expr": "g_periodic.handle != 0", "equals": 1 }, { "expr": "g_suspend_target.handle != 0", "equals": 1 }, { "expr": "g_observer.handle != 0", "equals": 1 } ] } }, "task01.periodic-entry": { "event_id": "E03", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 3 && $a1 == &g_periodic" }, "verify": { "expressions": [ { "expr": "g_periodic.phase", "equals": 4 }, { "expr": "g_periodic.release_count", "equals": 0 } ] } }, "task01.states": { "event_id": "E04", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 4 && $a1 == &g_observer" }, "verify": { "expressions": [ { "expr": "g_observer.periodic_state", "equals": 2 }, { "expr": "g_observer.suspend_state", "equals": 3 } ] } }, "task01.resumed": { "event_id": "E05", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 5 && $a1 == &g_suspend_target" }, "verify": { "expressions": [ { "expr": "g_suspend_target.resumed", "equals": 1 }, { "expr": "g_suspend_target.phase", "equals": 4 } ] } }, "task01.release-1": { "event_id": "E06", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 6 && $a1 == &g_periodic" }, "verify": { "expressions": [ { "expr": "g_periodic.release_count", "equals": 1 }, { "expr": "g_periodic.release_tick[0] - g_periodic.initial_tick", "equals": 2 } ] } }, "task01.release-2": { "event_id": "E07", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 7 && $a1 == &g_periodic" }, "verify": { "expressions": [ { "expr": "g_periodic.release_count", "equals": 2 }, { "expr": "g_periodic.release_tick[1] - g_periodic.release_tick[0]", "equals": 2 } ] } }, "task01.release-3": { "event_id": "E08", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 8 && $a1 == &g_periodic" }, "verify": { "expressions": [ { "expr": "g_periodic.release_count", "equals": 3 }, { "expr": "g_periodic.release_tick[2] - g_periodic.release_tick[1]", "equals": 2 } ] } }, "task01.periodic-finished": { "event_id": "E09", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 9 && $a1 == &g_periodic" }, "verify": { "expressions": [ { "expr": "g_periodic.phase", "equals": 5 }, { "expr": "g_periodic.handle == 0", "equals": 1 } ] } }, "task01.pass": { "event_id": "E10", "stop": { "symbol": "fc04_checkpoint_committed", "offset": 0, "condition": "$a0 == 10 && $a1 == &g_observer" }, "verify": { "expressions": [ { "expr": "g_fc04_pass", "equals": 1 }, { "expr": "g_suspend_target.resumed", "equals": 1 }, { "expr": "g_periodic.release_count", "equals": 3 } ] } } } }, "sections": [ { "title": "A2 — Structure", "order": 20, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "landscape", "content_tex": "Konteksty aplikacyjne przechowują uchwyty, stan diagnostyczny i bounded evidence; nie kopiują prywatnych list kernela.", "assets": [ { "path": "assets/a2-structure.png", "html_path": "assets/a2-structure.svg", "source_path": "assets/a2-structure.puml", "caption": "A2 STRUCTURE — trzy konteksty i absolutna oś wybudzeń.", "label": "fig:a2-structure", "alt": "PeriodicContext, SuspendContext, ObserverContext i timeline.", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 940, "page_height": 560, "overview": true, "step_tiles": { "periodic": 1, "suspend": 1, "observer": 1, "timeline": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc04-a2-structure", "title": "A2 · konteksty i timeline", "task": { "id": "task01", "label": "Task01 · delay i stany" }, "block": { "id": "a2", "label": "A2 STRUCTURE", "description": "Konteksty C i ograniczona oś czasu." }, "phases": [ { "id": "contexts", "label": "CONTEXTS / TIMELINE", "steps": [ { "id": "periodic", "number": 1, "label": "periodic context owns wake evidence", "mode": "CODE", "strategy_ref": "code.state-model", "svg_label": "01", "svg_target": "Periodic", "code_ref": "include/task01_delay_state.h:23", "description": "Context zachowuje t0 i trzy release ticks.", "evidence": "Static storage przeżywa self-delete." }, { "id": "suspend", "number": 2, "label": "suspend context records explicit resume", "mode": "CODE", "strategy_ref": "code.state-model", "svg_label": "02", "svg_target": "Suspend", "code_ref": "include/task01_delay_state.h:37", "description": "Suspended nie ma time-based wake.", "evidence": "resumed zmienia się wyłącznie po vTaskResume." }, { "id": "observer", "number": 3, "label": "observer stores public eTaskState", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.state", "svg_label": "03", "svg_target": "Observer", "code_ref": "src/tasks/task01_delay_state.c:150", "snapshot_ref": "task01.states", "description": "Publiczne API odróżnia Blocked i Suspended.", "evidence": "eBlocked oraz eSuspended." }, { "id": "timeline", "number": 4, "label": "absolute timeline has exact deltas", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.timeline", "svg_label": "04", "svg_target": "Timeline", "code_ref": "src/tasks/task01_delay_state.c:168", "snapshot_ref": "task01.pass", "description": "Deltas nie zależą od momentu powrotu z pracy.", "evidence": "t0, t0+2, t0+4, t0+6." } ] } ] } } ] }, { "title": "A5 — Flow", "order": 40, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "landscape", "content_tex": "Sekwencja pokazuje przyczynę każdego przejścia i jawny moment zapisu dowodu.", "assets": [ { "path": "assets/a5-flow.png", "html_path": "assets/a5-flow.svg", "source_path": "assets/a5-flow.puml", "caption": "A5 FLOW — od konfiguracji do okresowych wybudzeń i PASS.", "label": "fig:a5-flow", "alt": "Sekwencja periodic, suspend target, observer i scheduler.", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 940, "page_height": 560, "overview": true, "step_tiles": { "config": 1, "scheduler": 1, "periodic-entry": 1, "states": 1, "resumed": 1, "release-1": 1, "release-2": 1, "release-3": 1, "periodic-finished": 1, "pass": 1 } }, "interactive": { "kind": "uml-sequence", "storage_key": "fc04-a5-flow", "title": "A5 · delay i resume", "task": { "id": "task01", "label": "Task01 · delay i stany" }, "block": { "id": "a5", "label": "A5 FLOW", "description": "Jeden deterministyczny przebieg E01–E10." }, "phases": [ { "id": "replay", "label": "DELAY / STATE / DELETE", "steps": [ { "id": "config", "number": 1, "label": "configuration committed", "mode": "RUN", "event_id": "E01", "strategy_ref": "run.state", "svg_label": "01", "code_ref": "src/tasks/task01_delay_state.c:227", "snapshot_ref": "task01.config", "description": "Czysta RAM i konfiguracja FC04.", "evidence": "Brak uchwytów przed create." }, { "id": "scheduler", "number": 2, "label": "three tasks created", "mode": "RUN", "event_id": "E02", "strategy_ref": "run.state", "svg_label": "02", "code_ref": "src/tasks/task01_delay_state.c:256", "snapshot_ref": "task01.scheduler", "description": "Wszystkie publiczne handle są ważne.", "evidence": "Priorytety 3,2,1." }, { "id": "periodic-entry", "number": 3, "label": "periodic starts and blocks", "mode": "RUN", "event_id": "E03", "strategy_ref": "run.timeline", "svg_label": "03", "code_ref": "src/tasks/task01_delay_state.c:87", "snapshot_ref": "task01.periodic-entry", "description": "t0 jest punktem odniesienia vTaskDelayUntil.", "evidence": "release_count=0." }, { "id": "states", "number": 4, "label": "observer sees Blocked and Suspended", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.state", "svg_label": "04", "code_ref": "src/tasks/task01_delay_state.c:150", "snapshot_ref": "task01.states", "description": "Oba stany mają różną przyczynę.", "evidence": "eBlocked i eSuspended." }, { "id": "resumed", "number": 5, "label": "target resumes and self-deletes", "mode": "RUN", "event_id": "E05", "strategy_ref": "run.state", "svg_label": "05", "code_ref": "src/tasks/task01_delay_state.c:122", "snapshot_ref": "task01.resumed", "description": "Wyższy priorytet preemptuje observera.", "evidence": "resumed=1." }, { "id": "release-1", "number": 6, "label": "release at t0 plus 2", "mode": "RUN", "event_id": "E06", "strategy_ref": "run.timeline", "svg_label": "06", "code_ref": "src/tasks/task01_delay_state.c:96", "snapshot_ref": "task01.release-1", "description": "Pierwszy absolute wake.", "evidence": "delta=2." }, { "id": "release-2", "number": 7, "label": "release at t0 plus 4", "mode": "RUN", "event_id": "E07", "strategy_ref": "run.timeline", "svg_label": "07", "code_ref": "src/tasks/task01_delay_state.c:96", "snapshot_ref": "task01.release-2", "description": "Drugi absolute wake.", "evidence": "delta=2." }, { "id": "release-3", "number": 8, "label": "release at t0 plus 6", "mode": "RUN", "event_id": "E08", "strategy_ref": "run.timeline", "svg_label": "08", "code_ref": "src/tasks/task01_delay_state.c:96", "snapshot_ref": "task01.release-3", "description": "Trzeci absolute wake.", "evidence": "delta=2." }, { "id": "periodic-finished", "number": 9, "label": "periodic clears handle before delete", "mode": "RUN", "event_id": "E09", "strategy_ref": "run.state", "svg_label": "09", "code_ref": "src/tasks/task01_delay_state.c:99", "snapshot_ref": "task01.periodic-finished", "description": "Context zachowuje forensic values.", "evidence": "phase=COMPLETED, handle=NULL." }, { "id": "pass", "number": 10, "label": "observer verifies PASS", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.pass", "svg_label": "10", "code_ref": "src/tasks/task01_delay_state.c:192", "snapshot_ref": "task01.pass", "description": "Observer sprawdza stany, timeline i stack.", "evidence": "PASS=1." } ] } ] } } ] }, { "title": "A6 — State", "order": 50, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "landscape", "content_tex": "Blocked ma warunek czasu lub zdarzenia; Suspended wymaga jawnego resume. Deleted nie oznacza natychmiastowego wymazania wszystkich śladów.", "assets": [ { "path": "assets/a6-state.png", "html_path": "assets/a6-state.svg", "source_path": "assets/a6-state.puml", "caption": "A6 STATE — Ready, Running, Blocked, Suspended i Deleted.", "label": "fig:a6-state", "alt": "Maszyna stanów taska FreeRTOS.", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 940, "page_height": 560, "overview": true, "step_tiles": { "ready": 1, "running": 1, "blocked": 1, "suspended": 1, "resumed-ready": 1, "completed": 1, "deleted": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc04-a6-state", "title": "A6 · stany taska", "task": { "id": "task01", "label": "Task01 · delay i stany" }, "block": { "id": "a6", "label": "A6 STATE", "description": "Przyczyny przejść między stanami taska." }, "phases": [ { "id": "states", "label": "TASK STATE", "steps": [ { "id": "ready", "number": 1, "label": "Ready waits for selection", "mode": "RUN", "event_id": "E02", "strategy_ref": "run.state", "svg_label": "01", "code_ref": "src/tasks/task01_delay_state.c:229", "snapshot_ref": "task01.scheduler", "description": "Created nie znaczy Running.", "evidence": "handle ważny przed startem." }, { "id": "running", "number": 2, "label": "highest Ready task runs", "mode": "RUN", "event_id": "E03", "strategy_ref": "run.state", "svg_label": "02", "code_ref": "src/tasks/task01_delay_state.c:72", "snapshot_ref": "task01.periodic-entry", "description": "Periodic ma priorytet 3.", "evidence": "PC/SP w periodic." }, { "id": "blocked", "number": 3, "label": "delay moves task to Blocked", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.state", "svg_label": "03", "code_ref": "src/tasks/task01_delay_state.c:92", "snapshot_ref": "task01.states", "description": "Wake tick istnieje.", "evidence": "eBlocked." }, { "id": "suspended", "number": 4, "label": "self-suspend has no wake tick", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.state", "svg_label": "04", "code_ref": "src/tasks/task01_delay_state.c:118", "snapshot_ref": "task01.states", "description": "Tylko jawne resume przywraca Ready.", "evidence": "eSuspended." }, { "id": "resumed-ready", "number": 5, "label": "resume makes target Ready", "mode": "RUN", "event_id": "E05", "strategy_ref": "run.state", "svg_label": "05", "code_ref": "src/tasks/task01_delay_state.c:160", "snapshot_ref": "task01.resumed", "description": "Priorytet 2 wyprzedza observera 1.", "evidence": "target Running po resume." }, { "id": "completed", "number": 6, "label": "application records completion", "mode": "RUN", "event_id": "E09", "strategy_ref": "run.state", "svg_label": "06", "code_ref": "src/tasks/task01_delay_state.c:99", "snapshot_ref": "task01.periodic-finished", "description": "COMPLETED jest stanem diagnostycznym aplikacji.", "evidence": "Zapis przed delete." }, { "id": "deleted", "number": 7, "label": "self-delete delegates cleanup", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.pass", "svg_label": "07", "code_ref": "src/tasks/task01_delay_state.c:102", "snapshot_ref": "task01.pass", "description": "Idle może później odzyskać TCB/stack.", "evidence": "Context static pozostaje." } ] } ] } } ] }, { "title": "A7 — Runtime", "order": 60, "content_kind": "prose", "asset_page_mode": "one-per-page", "page_orientation": "landscape", "content_tex": "A7 wiąże publiczne eTaskState z pamięcią taska i bounded evidence, bez uzależniania programu od pxCurrentTCB.", "assets": [ { "path": "assets/a7-runtime.png", "html_path": "assets/a7-runtime.svg", "source_path": "assets/a7-runtime.puml", "caption": "A7 RUNTIME — stany publiczne, task memory, wake ticks i PASS.", "label": "fig:a7-runtime", "alt": "Runtime evidence dla delay i suspend.", "kind": "diagram", "width": 1.0, "page_grid": { "columns": 1, "rows": 1, "page_width": 940, "page_height": 560, "overview": true, "step_tiles": { "public": 1, "periodic-runtime": 1, "wake": 1, "suspend-runtime": 1, "evidence": 1 } }, "interactive": { "kind": "uml-class", "storage_key": "fc04-a7-runtime", "title": "A7 · runtime evidence", "task": { "id": "task01", "label": "Task01 · delay i stany" }, "block": { "id": "a7", "label": "A7 RUNTIME", "description": "Publiczny stan, TCB/stack i oś ticków." }, "phases": [ { "id": "runtime", "label": "STATE / MEMORY / TIME", "steps": [ { "id": "public", "number": 1, "label": "public API exposes two states", "mode": "RUN", "event_id": "E04", "strategy_ref": "run.state", "svg_label": "01", "svg_target": "Public", "code_ref": "src/tasks/task01_delay_state.c:150", "snapshot_ref": "task01.states", "description": "Program nie czyta prywatnych list.", "evidence": "eBlocked, eSuspended." }, { "id": "periodic-runtime", "number": 2, "label": "periodic has separate TCB and stack", "mode": "RUN", "event_id": "E03", "strategy_ref": "run.timeline", "svg_label": "02", "svg_target": "Periodic", "code_ref": "src/tasks/task01_delay_state.c:59", "snapshot_ref": "task01.periodic-entry", "description": "SP należy do task stack.", "evidence": "created_handle i stack range." }, { "id": "wake", "number": 3, "label": "absolute wake timeline is exact", "mode": "RUN", "event_id": "E08", "strategy_ref": "run.timeline", "svg_label": "03", "svg_target": "Wake", "code_ref": "src/tasks/task01_delay_state.c:96", "snapshot_ref": "task01.release-3", "description": "Trzy wybudzenia zachowują okres.", "evidence": "2/4/6." }, { "id": "suspend-runtime", "number": 4, "label": "suspended task resumes explicitly", "mode": "RUN", "event_id": "E05", "strategy_ref": "run.state", "svg_label": "04", "svg_target": "Suspend", "code_ref": "src/tasks/task01_delay_state.c:107", "snapshot_ref": "task01.resumed", "description": "Brak time-based wake.", "evidence": "resumed=1." }, { "id": "evidence", "number": 5, "label": "forensic evidence remains bounded", "mode": "RUN", "event_id": "E10", "strategy_ref": "run.pass", "svg_label": "05", "svg_target": "Evidence", "code_ref": "src/tasks/task01_delay_state.c:192", "snapshot_ref": "task01.pass", "description": "Snapshot wiąże wynik ze źródłem i ELF.", "evidence": "PASS, source blob, image hash, timestamp." } ] } ] } } ] }, { "title": "Task01 — delay i stany", "order": 90, "content_kind": "tasks", "task_refs": [ "task01" ] } ], "tasks": { "task01": { "title": "Delay, blokowanie, zawieszenie i self-delete", "uuid": "4a7ef04c-ab08-5783-9192-5b02a90f05f8", "prompt_tex": "Przejdź po A2, A5, A6 i A7. Odtwórz E01–E10, rozróżnij Blocked od Suspended i udowodnij dokładny okres vTaskDelayUntil.", "criterion": "Program kończy się PASS; observer widzi eBlocked i eSuspended; timeline ma dokładne delty 2; resume działa raz; context, TCB i stack pozostają rozdzielone.", "conclusion_tex": "Blocked task ma warunek wybudzenia, Suspended wymaga jawnego resume, a vTaskDelayUntil utrzymuje absolutną fazę okresu. Self-delete kończy task, lecz aplikacyjny context może zachować bounded forensic evidence.", "flow": [ { "kind": "block", "id": "state-model", "title": "A — model stanów", "content_tex": "Najpierw przewidź przyczynę i wyjście z każdego stanu.", "steps": [ { "id": "classify", "title": "Sklasyfikuj Blocked i Suspended.", "content_tex": "Wskaż warunek automatycznego wybudzenia albo jego brak." }, { "id": "predict", "title": "Przewidź oś czasu.", "content_tex": "Zapisz oczekiwane t0+2, t0+4 i t0+6." } ] }, { "kind": "block", "id": "runtime-replay", "title": "B — replay Hazard3", "content_tex": "Każdy RUN zaczyna się od czystej RAM.", "steps": [ { "id": "observe", "title": "Zbadaj E04.", "content_tex": "Zapisz publiczne stany obu tasków i ich przyczyny." }, { "id": "resume", "title": "Zbadaj E05.", "content_tex": "Wyjaśnij, dlaczego target preemptuje observera." }, { "id": "timeline", "title": "Zbadaj E06–E08.", "content_tex": "Policz delty release ticks i sprawdź stack taska." }, { "id": "finish", "title": "Zbadaj E09–E10.", "content_tex": "Oddziel application completion od cleanup kernela." } ] }, { "kind": "exercise", "id": "relative-delay-drift", "title": "Ćwiczenie — względny delay i dryf", "prompt_tex": "Zastąp vTaskDelayUntil przez vTaskDelay i dodaj bounded workload trwający jeden tick po każdym wybudzeniu. Zmierz trzy release ticks i porównaj fazę z wersją bazową.", "evidence_tex": "Timestampowane snapshoty release ticks oraz krótka tabela różnic względem 2/4/6.", "criterion": "Uczeń poprawnie wyjaśnia, dlaczego relative delay kumuluje czas pracy i przesuwa fazę.", "based_on": [ "state-model", "runtime-replay" ] } ], "educational_requirement_refs": [ "FC04.WE01" ], "learning_effect_refs": [ "FC04.EN01", "FC04.EK01" ], "assessment_criterion_ref": "FC04.KW01" } }, "tasks_order": [ "task01" ] }