Files
lab-rv32i-freertos-c-resour…/json/card_source.json
T

1461 lines
48 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "../../../tools/card-layouts/schemas/card-source.schema.json",
"schema": "esc-card-source.v1",
"card": {
"id": "mpabi-freertos-c-08-mutex-priority-inheritance",
"series": "freertos-c",
"series_title": "FreeRTOS C",
"number": "08",
"count": "15",
"slug": "mutex-priority-inheritance",
"title": "Mutex i dziedziczenie priorytetu",
"topic": "ownership, bounded inversion i priority inheritance",
"project": "Freestanding C nad FreeRTOS",
"subject": "Informatyka",
"level": "Rok 2 · L08 · RV32I/Hazard3",
"revision_date": "2026-07-19T00:00:00+02:00",
"status": "Gotowa",
"version": "v00.01",
"uuid": "b408a0e1-ca9f-52b8-9075-ff324bfce778",
"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 aplikacjakernelHazard3 jest utrwalona w FC07."
},
{
"id": "A2",
"label": "STRUCTURE",
"subtitle": "Mutex, owner, wait list i zasób",
"status": "enabled",
"target_label": "fig:a2-structure"
},
{
"id": "A3",
"label": "DISPATCH",
"subtitle": "Binding",
"status": "unavailable",
"reason": "FC08 nie wprowadza callbacku ani granicy ISR."
},
{
"id": "A4",
"label": "APPLICATION",
"subtitle": "Low, Medium, High i verifier",
"status": "enabled",
"target_label": "fig:a4-application"
},
{
"id": "A5",
"label": "FLOW",
"subtitle": "E01E10 i handoff mutexu",
"status": "enabled",
"target_label": "fig:a5-flow"
},
{
"id": "A6",
"label": "STATE",
"subtitle": "Owner, waiter i effective priority",
"status": "enabled",
"target_label": "fig:a6-state"
},
{
"id": "A7",
"label": "RUNTIME",
"subtitle": "Handle, TCB, stos i event log",
"status": "enabled",
"target_label": "fig:a7-runtime"
},
{
"id": "A8",
"label": "PATTERNS",
"subtitle": "Critical, suspend, mutex, gatekeeper",
"status": "enabled",
"target_label": "fig:a8-patterns"
}
],
"debug_strategies": {
"code.contract": {
"id": "code.contract",
"kind": "code",
"action": "open",
"expected_observations": [
"genuine mutex API",
"brak vTaskPrioritySet"
],
"assertions": [
"one mutex",
"fixed p1/p2/p3"
],
"evidence_fields": [
"code_ref",
"API",
"priority"
],
"prerequisites": [
"źródło FC08"
],
"layout": [
"FreeRTOSConfig",
"MutexExperiment",
"task priorities"
],
"commands": [
"rg -n 'configUSE_MUTEXES|xSemaphore|uxTaskPriorityGet' include src"
]
},
"run.inheritance": {
"id": "run.inheritance",
"kind": "run",
"action": "replay",
"expected_observations": [
"Low effective=3",
"Medium Ready and not started"
],
"assertions": [
"holder=Low",
"High uses portMAX_DELAY"
],
"evidence_fields": [
"event",
"holder",
"priority",
"state",
"PC",
"SP",
"timestamp"
],
"prerequisites": [
"Hazard3 online",
"czysta RAM"
],
"layout": [
"Low/High/Medium",
"mutex holder",
"task states",
"event log"
],
"commands": [
"print g_fc08",
"print g_fc08_events"
]
},
"run.handoff": {
"id": "run.handoff",
"kind": "run",
"action": "replay",
"expected_observations": [
"High E07 before Medium E08",
"value 2 under High ownership"
],
"assertions": [
"Low restored to 1",
"resource invariant"
],
"evidence_fields": [
"order",
"priority",
"value"
],
"prerequisites": [
"Low owns contended mutex"
],
"layout": [
"give path",
"High",
"Medium",
"protected value"
],
"commands": [
"print g_fc08.protected_value",
"print g_fc08_events[6]",
"print g_fc08_events[7]"
]
},
"run.pass": {
"id": "run.pass",
"kind": "run",
"action": "replay",
"expected_observations": [
"PASS=1",
"10 committed records"
],
"assertions": [
"stable three-run digest",
"verifier priority 0"
],
"evidence_fields": [
"PASS",
"digest",
"source blob",
"ELF hash",
"timestamp"
],
"prerequisites": [
"three workers finished"
],
"layout": [
"bounded log",
"PASS",
"digest"
],
"commands": [
"print g_fc08_pass",
"print g_fc08.evidence_digest"
]
}
},
"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": "Mutex i dziedziczenie priorytetu",
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/2392f81a-ed6c-510b-86b5-06c5e2f1c6aa",
"repository_url": "https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-c-resource-management",
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
"url_domain": "mpabi.pl",
"doc_uuid": "2392f81a-ed6c-510b-86b5-06c5e2f1c6aa",
"revision": "v00.01",
"issued_on": "2026-07-19T00:00:00+02:00",
"series": "FREERTOS-C-08",
"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 mutex od semafora binarnego i dowodzi, że FreeRTOS tymczasowo podnosi efektywny priorytet właściciela blokującego task o wyższym priorytecie.",
"scope_title": "Zakres karty",
"scope_content_tex": "Low p1 przejmuje mutex i tworzy High p3. High blokuje się bez timeoutu, Low dziedziczy p3, a nowy Medium p2 pozostaje Ready bez wykonania. Po give High przejmuje zasób przed Medium, a Low wraca do p1. Verifier sprawdza publiczne API, własność, trzy stosy, porządek E01E10 i stabilny digest.",
"scope_table": {
"headers": [
"Lekcja",
"Task",
"Najważniejsza idea",
"Priorytet",
"Status",
"Version"
],
"rows": [
{
"chapter": "FC08",
"task": "Task01",
"idea_tex": "ownership, bounded inversion i priority inheritance",
"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": {
"FC08.EN01": {
"bloom_level": "Analiza",
"label": "Model mutexu",
"text": "Uczeń wiąże ownership, wait list i effective priority bez ręcznej zmiany priorytetu.",
"assessment_criteria": [
"FC08.KW01"
]
},
"FC08.EK01": {
"bloom_level": "Zastosowanie",
"label": "Replay PIP",
"text": "Uczeń odtwarza E01E10 i pokazuje holder, publiczne priority/state, trzy stosy, protected value i digest.",
"assessment_criteria": [
"FC08.KW01"
]
}
},
"assessment_criteria": {
"FC08.KW01": {
"text": "PASS; Low 1→3→1; Medium eReady i started=0 podczas dziedziczenia; High E07 przed Medium E08; digest jest deterministyczny.",
"learning_effects": [
"FC08.EN01",
"FC08.EK01"
]
}
},
"educational_requirements": {
"FC08.WE01": {
"text": "Zbadanie mechanizmu bounded priority inversion na prawdziwym mutexie FreeRTOS.",
"label": "ownership, bounded inversion i priority inheritance",
"learning_effects": [
"FC08.EN01",
"FC08.EK01"
],
"learning_tree": {
"schema": "we-learning-tree.v1",
"policy": "Każda aktywna kotwica wskazuje kod lub checkpoint.",
"ogolne": [
{
"effect_ref": "FC08.EN01",
"display": "EN LOCAL RTOS.08",
"source": "LOCAL",
"official": "RTOS",
"local": "08",
"kind": "EN",
"tree_id": "FC08.WE01.OG.LOCAL.RTOS.08",
"text": "Uczeń wiąże ownership, wait list i effective priority bez ręcznej zmiany priorytetu.",
"kw": [
{
"criterion_ref": "FC08.KW01",
"display": "KW LOCAL RTOS.08",
"source": "LOCAL",
"kind": "KW",
"official": "RTOS",
"local": "08",
"text": "Łączy kod, diagram i zweryfikowany dowód."
}
]
}
],
"zawodowe": [
{
"effect_ref": "FC08.EK01",
"display": "EK LOCAL RTOS.08",
"source": "LOCAL",
"official": "RTOS",
"local": "08",
"kind": "EK",
"tree_id": "FC08.WE01.TECH.LOCAL.RTOS.08",
"text": "Uczeń odtwarza E01E10 i pokazuje holder, publiczne priority/state, trzy stosy, protected value i digest.",
"kw": [
{
"criterion_ref": "FC08.KW01",
"display": "KW LOCAL RTOS.08",
"source": "LOCAL",
"kind": "KW",
"official": "RTOS",
"local": "08",
"text": "Łączy kod, diagram i zweryfikowany dowód."
}
]
}
]
}
}
},
"debug_checkpoints": {
"schema": "stem-debug-checkpoints.v1",
"semantics": "deterministic-replay",
"artifact": {
"source": "src/tasks/task01_mutex.c",
"source_git_blob": "520c0396319fb331443650c1664dfb692a806e44",
"elf": "build/task01_mutex/prog.elf",
"hazard3_elf_sha256": "9a02076cc36ed00ad1ca23e90c756f30cb69524fe6531983b536538bf5ebd388",
"hazard3_image": "build/task01_mutex/prog.bin",
"hazard3_image_sha256": "89802a1007fc59f285d07da7ba002b6593ae2cf9891df151af8182fe8bfe9b04"
},
"targets": {
"hazard3-sim": {
"adapter": "hazard3-reset-load-replay.v1",
"baseline": "restart-backend",
"clean_ram": true
}
},
"items": {
"task01.config": {
"event_id": "E01",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 1"
},
"verify": {
"expressions": [
{
"expr": "g_fc08_event_count",
"equals": 1
}
]
}
},
"task01.low-owns": {
"event_id": "E02",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 2"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.protected_value",
"equals": 1
},
{
"expr": "g_fc08.low_sp != 0",
"equals": 1
}
]
}
},
"task01.high-blocks": {
"event_id": "E03",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 3"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.high_sp != 0",
"equals": 1
}
]
}
},
"task01.inherited": {
"event_id": "E04",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 4"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.inherited_priority",
"equals": 3
},
{
"expr": "g_fc08.holder_while_contended == g_fc08.low_handle",
"equals": 1
}
]
}
},
"task01.medium-ready": {
"event_id": "E05",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 5"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.medium_state_while_inherited",
"equals": 1
},
{
"expr": "g_fc08.medium_started_while_inherited",
"equals": 0
}
]
}
},
"task01.release": {
"event_id": "E06",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 6"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.protected_value",
"equals": 1
}
]
}
},
"task01.high-acquires": {
"event_id": "E07",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 7"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.high_acquired",
"equals": 1
},
{
"expr": "g_fc08.protected_value",
"equals": 2
}
]
}
},
"task01.medium-runs": {
"event_id": "E08",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 8"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.medium_started",
"equals": 1
},
{
"expr": "g_fc08_events[6].event",
"equals": 7
}
]
}
},
"task01.restored": {
"event_id": "E09",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 9"
},
"verify": {
"expressions": [
{
"expr": "g_fc08.restored_priority",
"equals": 1
}
]
}
},
"task01.pass": {
"event_id": "E10",
"stop": {
"symbol": "fc08_checkpoint_committed",
"offset": 0,
"condition": "$a0 == 10"
},
"verify": {
"expressions": [
{
"expr": "g_fc08_pass",
"equals": 1
},
{
"expr": "g_fc08_event_count",
"equals": 10
}
]
}
}
}
},
"sections": [
{
"title": "A2 — Structure",
"order": 20,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "Mutex przechowuje właściciela i wait list. Dziedziczenie zmienia efektywny priorytet właściciela, nie bazową konfigurację aplikacji.",
"assets": [
{
"path": "assets/a2-structure.png",
"html_path": "assets/a2-structure.svg",
"source_path": "assets/a2-structure.puml",
"caption": "A2 STRUCTURE — ownership i wait list.",
"label": "fig:a2-structure",
"alt": "Struktura mutexu i trzech tasków.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"mutex": 1,
"low": 1,
"high": 1,
"medium": 1,
"resource": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc08-a2-structure",
"title": "A2 · struktura mutexu",
"task": {
"id": "task01",
"label": "Task01 · mutex i PIP"
},
"block": {
"id": "a2",
"label": "A2 STRUCTURE",
"description": "Genuine mutex, owner, waiter, Ready task and guarded resource."
},
"phases": [
{
"id": "structure",
"label": "MUTEX / OWNER / WAITERS",
"steps": [
{
"id": "mutex",
"number": 1,
"label": "genuine FreeRTOS mutex",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "src/tasks/task01_mutex.c:237",
"description": "xSemaphoreCreateMutex wybiera mechanizm ownership/PIP.",
"evidence": "xQueueCreateMutex symbol."
},
{
"id": "low",
"number": 2,
"label": "Low owns protected value",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.inheritance",
"svg_label": "02",
"code_ref": "src/tasks/task01_mutex.c:142",
"snapshot_ref": "task01.low-owns",
"description": "Take z zerowym wait jest legalny dla wolnego mutexu.",
"evidence": "holder Low; value 1."
},
{
"id": "high",
"number": 3,
"label": "High waits indefinitely",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.inheritance",
"svg_label": "03",
"code_ref": "src/tasks/task01_mutex.c:97",
"snapshot_ref": "task01.high-blocks",
"description": "High trafia na mutex wait list.",
"evidence": "High stack and Blocked path."
},
{
"id": "medium",
"number": 4,
"label": "Medium is Ready, not executed",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.inheritance",
"svg_label": "04",
"code_ref": "src/tasks/task01_mutex.c:160",
"snapshot_ref": "task01.medium-ready",
"description": "P2 nie wyprzedza odziedziczonego p3.",
"evidence": "eReady; started=0."
},
{
"id": "resource",
"number": 5,
"label": "all writes occur under ownership",
"mode": "RUN",
"event_id": "E07",
"strategy_ref": "run.handoff",
"svg_label": "05",
"code_ref": "src/tasks/task01_mutex.c:101",
"snapshot_ref": "task01.high-acquires",
"description": "High zapisuje 2 po przejęciu mutexu.",
"evidence": "protected_value=2."
}
]
}
]
}
}
]
},
{
"title": "A4 — Application",
"order": 30,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "Low tworzy High dopiero po przejęciu mutexu, a Medium dopiero po potwierdzeniu dziedziczenia. Topologia jest deterministyczna.",
"assets": [
{
"path": "assets/a4-application.png",
"html_path": "assets/a4-application.svg",
"source_path": "assets/a4-application.puml",
"caption": "A4 APPLICATION — deterministic creation topology.",
"label": "fig:a4-application",
"alt": "Topologia Low, High, Medium i verifier.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"main": 1,
"low": 1,
"high": 1,
"inherited": 1,
"medium": 1,
"verifier": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc08-a4-application",
"title": "A4 · topologia eksperymentu",
"task": {
"id": "task01",
"label": "Task01 · mutex i PIP"
},
"block": {
"id": "a4",
"label": "A4 APPLICATION",
"description": "Construction order makes inheritance observable without timing guesses."
},
"phases": [
{
"id": "topology",
"label": "CREATE / BLOCK / VERIFY",
"steps": [
{
"id": "main",
"number": 1,
"label": "main creates only Low and verifier",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "src/tasks/task01_mutex.c:233",
"description": "High nie może przejąć wolnego mutexu przed Low.",
"evidence": "fixed topology."
},
{
"id": "low",
"number": 2,
"label": "Low creates High while owning",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.inheritance",
"svg_label": "02",
"code_ref": "src/tasks/task01_mutex.c:149",
"snapshot_ref": "task01.low-owns",
"description": "High natychmiast preemptuje i blokuje się.",
"evidence": "next event E03."
},
{
"id": "high",
"number": 3,
"label": "High creates contention",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.inheritance",
"svg_label": "03",
"code_ref": "src/tasks/task01_mutex.c:96",
"snapshot_ref": "task01.high-blocks",
"description": "Nie ma sztucznej zmiany priorytetu.",
"evidence": "real mutex wait."
},
{
"id": "inherited",
"number": 4,
"label": "Low continues at effective p3",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.inheritance",
"svg_label": "04",
"code_ref": "src/tasks/task01_mutex.c:152",
"snapshot_ref": "task01.inherited",
"description": "Public API zwraca 3.",
"evidence": "holder remains Low."
},
{
"id": "medium",
"number": 5,
"label": "Medium is the inversion probe",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.inheritance",
"svg_label": "05",
"code_ref": "src/tasks/task01_mutex.c:162",
"snapshot_ref": "task01.medium-ready",
"description": "Ready p2 nie wykonuje nawet pierwszej instrukcji.",
"evidence": "started=0."
},
{
"id": "verifier",
"number": 6,
"label": "lowest verifier asserts relations",
"mode": "RUN",
"event_id": "E10",
"strategy_ref": "run.pass",
"svg_label": "06",
"code_ref": "src/tasks/task01_mutex.c:207",
"snapshot_ref": "task01.pass",
"description": "Sprawdzenie nie zakłóca workerów.",
"evidence": "PASS and digest."
}
]
}
]
}
}
]
},
{
"title": "A5 — Flow",
"order": 40,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "Decydujący porządek to High blocks → Low inherits → Medium Ready/not-run → give → High acquires → Medium runs.",
"assets": [
{
"path": "assets/a5-flow.png",
"html_path": "assets/a5-flow.svg",
"source_path": "assets/a5-flow.puml",
"caption": "A5 FLOW — bounded priority inversion.",
"label": "fig:a5-flow",
"alt": "Sekwencja dziedziczenia priorytetu.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"config": 1,
"own": 1,
"block": 1,
"inherit": 1,
"ready": 1,
"give": 1,
"high": 1,
"medium": 1,
"restore": 1,
"pass": 1
}
},
"interactive": {
"kind": "uml-sequence",
"storage_key": "fc08-a5-flow",
"title": "A5 · priority inheritance flow",
"task": {
"id": "task01",
"label": "Task01 · mutex i PIP"
},
"block": {
"id": "a5",
"label": "A5 FLOW",
"description": "One complete E01E10 run."
},
"phases": [
{
"id": "flow",
"label": "OWN / INHERIT / HANDOFF / RESTORE",
"steps": [
{
"id": "config",
"number": 1,
"label": "configuration committed",
"mode": "RUN",
"event_id": "E01",
"strategy_ref": "run.inheritance",
"svg_label": "01",
"code_ref": "src/tasks/task01_mutex.c:236",
"snapshot_ref": "task01.config",
"description": "Clean RAM and fixed priorities.",
"evidence": "one record."
},
{
"id": "own",
"number": 2,
"label": "Low takes mutex",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.inheritance",
"svg_label": "02",
"code_ref": "src/tasks/task01_mutex.c:142",
"snapshot_ref": "task01.low-owns",
"description": "Low becomes owner.",
"evidence": "value=1."
},
{
"id": "block",
"number": 3,
"label": "High blocks",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.inheritance",
"svg_label": "03",
"code_ref": "src/tasks/task01_mutex.c:97",
"snapshot_ref": "task01.high-blocks",
"description": "Non-zero wait creates contention.",
"evidence": "High stack."
},
{
"id": "inherit",
"number": 4,
"label": "Low inherits p3",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.inheritance",
"svg_label": "04",
"code_ref": "src/tasks/task01_mutex.c:152",
"snapshot_ref": "task01.inherited",
"description": "Kernel PIP, not application code.",
"evidence": "priority=3."
},
{
"id": "ready",
"number": 5,
"label": "Medium Ready but not run",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.inheritance",
"svg_label": "05",
"code_ref": "src/tasks/task01_mutex.c:162",
"snapshot_ref": "task01.medium-ready",
"description": "Bounded inversion proof.",
"evidence": "eReady and zero flag."
},
{
"id": "give",
"number": 6,
"label": "Low begins give",
"mode": "RUN",
"event_id": "E06",
"strategy_ref": "run.handoff",
"svg_label": "06",
"code_ref": "src/tasks/task01_mutex.c:169",
"snapshot_ref": "task01.release",
"description": "High may preempt inside API.",
"evidence": "value still 1."
},
{
"id": "high",
"number": 7,
"label": "High acquires first",
"mode": "RUN",
"event_id": "E07",
"strategy_ref": "run.handoff",
"svg_label": "07",
"code_ref": "src/tasks/task01_mutex.c:101",
"snapshot_ref": "task01.high-acquires",
"description": "Ownership transfers to top waiter.",
"evidence": "value=2."
},
{
"id": "medium",
"number": 8,
"label": "Medium runs after High",
"mode": "RUN",
"event_id": "E08",
"strategy_ref": "run.handoff",
"svg_label": "08",
"code_ref": "src/tasks/task01_mutex.c:123",
"snapshot_ref": "task01.medium-runs",
"description": "No priority inversion remains.",
"evidence": "E07 before E08."
},
{
"id": "restore",
"number": 9,
"label": "Low returns to base p1",
"mode": "RUN",
"event_id": "E09",
"strategy_ref": "run.handoff",
"svg_label": "09",
"code_ref": "src/tasks/task01_mutex.c:175",
"snapshot_ref": "task01.restored",
"description": "Disinherit after give.",
"evidence": "priority=1."
},
{
"id": "pass",
"number": 10,
"label": "verifier commits PASS",
"mode": "RUN",
"event_id": "E10",
"strategy_ref": "run.pass",
"svg_label": "10",
"code_ref": "src/tasks/task01_mutex.c:207",
"snapshot_ref": "task01.pass",
"description": "All relational assertions hold.",
"evidence": "digest 5433b784."
}
]
}
]
}
}
]
},
{
"title": "A6 — State",
"order": 50,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "High nie przejmuje zasobu w chwili blokady. Kernel tymczasowo podnosi właściciela, a dopiero give przenosi własność i przywraca bazowy priorytet.",
"assets": [
{
"path": "assets/a6-state.png",
"html_path": "assets/a6-state.svg",
"source_path": "assets/a6-state.puml",
"caption": "A6 STATE — free, owned, contended, transferred.",
"label": "fig:a6-state",
"alt": "Maszyna stanu mutexu.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"free": 1,
"owned": 1,
"contended": 1,
"transfer": 1,
"verified": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc08-a6-state",
"title": "A6 · owner and priority state",
"task": {
"id": "task01",
"label": "Task01 · mutex i PIP"
},
"block": {
"id": "a6",
"label": "A6 STATE",
"description": "Mutex ownership and effective-priority states."
},
"phases": [
{
"id": "state",
"label": "FREE / OWNED / CONTENDED / TRANSFERRED",
"steps": [
{
"id": "free",
"number": 1,
"label": "mutex starts free",
"mode": "RUN",
"event_id": "E01",
"strategy_ref": "run.inheritance",
"svg_label": "01",
"code_ref": "src/tasks/task01_mutex.c:237",
"snapshot_ref": "task01.config",
"description": "No owner.",
"evidence": "handle created after E01."
},
{
"id": "owned",
"number": 2,
"label": "Low owns at p1",
"mode": "RUN",
"event_id": "E02",
"strategy_ref": "run.inheritance",
"svg_label": "02",
"code_ref": "src/tasks/task01_mutex.c:142",
"snapshot_ref": "task01.low-owns",
"description": "Uncontended state.",
"evidence": "protected value 1."
},
{
"id": "contended",
"number": 3,
"label": "High waits; Low effective p3",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.inheritance",
"svg_label": "03",
"code_ref": "src/tasks/task01_mutex.c:152",
"snapshot_ref": "task01.inherited",
"description": "Owner stays Low.",
"evidence": "priority 3, holder Low."
},
{
"id": "transfer",
"number": 6,
"label": "give transfers to High",
"mode": "RUN",
"event_id": "E07",
"strategy_ref": "run.handoff",
"svg_label": "06",
"code_ref": "src/tasks/task01_mutex.c:103",
"snapshot_ref": "task01.high-acquires",
"description": "High returns from take.",
"evidence": "value 2."
},
{
"id": "verified",
"number": 9,
"label": "Low is restored",
"mode": "RUN",
"event_id": "E09",
"strategy_ref": "run.handoff",
"svg_label": "09",
"code_ref": "src/tasks/task01_mutex.c:175",
"snapshot_ref": "task01.restored",
"description": "Effective equals base again.",
"evidence": "priority 1."
}
]
}
]
}
}
]
},
{
"title": "A7 — Runtime",
"order": 60,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "portrait",
"content_tex": "Aplikacja asercyjnie używa wyłącznie publicznego API. uxBasePriority i uxPriority są dowodem debuggera, a nie kontraktem kodu ucznia.",
"assets": [
{
"path": "assets/a7-runtime.png",
"html_path": "assets/a7-runtime.svg",
"source_path": "assets/a7-runtime.puml",
"caption": "A7 RUNTIME — handles, stacks, public states and TCB detail.",
"label": "fig:a7-runtime",
"alt": "Runtime mutexu i trzech tasków.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 660,
"page_height": 760,
"overview": true,
"step_tiles": {
"experiment": 1,
"low": 1,
"high": 1,
"medium": 1,
"tcb": 1,
"log": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc08-a7-runtime",
"title": "A7 · runtime evidence",
"task": {
"id": "task01",
"label": "Task01 · mutex i PIP"
},
"block": {
"id": "a7",
"label": "A7 RUNTIME",
"description": "Public acceptance evidence plus optional TCB inspection."
},
"phases": [
{
"id": "runtime",
"label": "HANDLES / STACKS / TCB / LOG",
"steps": [
{
"id": "experiment",
"number": 1,
"label": "experiment owns bounded evidence",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "include/task01_mutex.h:26",
"description": "Persistent static context.",
"evidence": "handles and observations."
},
{
"id": "low",
"number": 2,
"label": "Low handle remains forensic identity",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.inheritance",
"svg_label": "02",
"code_ref": "src/tasks/task01_mutex.c:153",
"snapshot_ref": "task01.inherited",
"description": "Holder compares to saved handle.",
"evidence": "SP and priority."
},
{
"id": "high",
"number": 3,
"label": "High owns distinct stack",
"mode": "RUN",
"event_id": "E03",
"strategy_ref": "run.inheritance",
"svg_label": "03",
"code_ref": "src/tasks/task01_mutex.c:95",
"snapshot_ref": "task01.high-blocks",
"description": "Blocked task preserves context.",
"evidence": "high_sp."
},
{
"id": "medium",
"number": 4,
"label": "Medium state is public eReady",
"mode": "RUN",
"event_id": "E05",
"strategy_ref": "run.inheritance",
"svg_label": "04",
"code_ref": "src/tasks/task01_mutex.c:162",
"snapshot_ref": "task01.medium-ready",
"description": "No private TCB dependency.",
"evidence": "eTaskGetState."
},
{
"id": "tcb",
"number": 5,
"label": "TCB base/effective is debugger evidence",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.inheritance",
"svg_label": "05",
"code_ref": "vendor/FreeRTOS-Kernel/tasks.c:1000",
"snapshot_ref": "task01.inherited",
"description": "Inspect uxBasePriority and uxPriority only in GDB.",
"evidence": "1 and 3."
},
{
"id": "log",
"number": 6,
"label": "record commits marker last",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "06",
"code_ref": "src/tasks/task01_mutex.c:55",
"description": "Partial record cannot masquerade as evidence.",
"evidence": "committed after payload."
}
]
}
]
}
}
]
},
{
"title": "A8 — Patterns",
"order": 70,
"content_kind": "prose",
"asset_page_mode": "one-per-page",
"page_orientation": "landscape",
"content_tex": "Critical section, scheduler suspension, mutex and gatekeeper solve different problems. FC08 requires task ownership and priority inheritance, therefore selects a mutex.",
"assets": [
{
"path": "assets/a8-patterns.png",
"html_path": "assets/a8-patterns.svg",
"source_path": "assets/a8-patterns.puml",
"caption": "A8 PATTERNS — four distinct synchronization contracts.",
"label": "fig:a8-patterns",
"alt": "Porównanie czterech wzorców ochrony zasobu.",
"kind": "diagram",
"width": 1.0,
"page_grid": {
"columns": 1,
"rows": 1,
"page_width": 940,
"page_height": 560,
"overview": true,
"step_tiles": {
"critical": 1,
"suspend": 1,
"mutex": 1,
"gatekeeper": 1
}
},
"interactive": {
"kind": "uml-class",
"storage_key": "fc08-a8-patterns",
"title": "A8 · resource-management choices",
"task": {
"id": "task01",
"label": "Task01 · mutex i PIP"
},
"block": {
"id": "a8",
"label": "A8 PATTERNS",
"description": "Select synchronization by contract, not by similar syntax."
},
"phases": [
{
"id": "patterns",
"label": "CRITICAL / SUSPEND / MUTEX / GATEKEEPER",
"steps": [
{
"id": "critical",
"number": 1,
"label": "critical section is bounded and nonblocking",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "01",
"code_ref": "src/tasks/task01_mutex.c:48",
"description": "Protects evidence commit only.",
"evidence": "short interrupt mask."
},
{
"id": "suspend",
"number": 2,
"label": "scheduler suspension is not a lock",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "02",
"code_ref": "doc/card-plan.md:1",
"description": "Interrupts continue and ownership is absent.",
"evidence": "not selected."
},
{
"id": "mutex",
"number": 3,
"label": "mutex owns and inherits",
"mode": "RUN",
"event_id": "E04",
"strategy_ref": "run.inheritance",
"svg_label": "03",
"code_ref": "src/tasks/task01_mutex.c:152",
"snapshot_ref": "task01.inherited",
"description": "Selected FC08 contract.",
"evidence": "holder Low, effective 3."
},
{
"id": "gatekeeper",
"number": 4,
"label": "gatekeeper serializes by message",
"mode": "CODE",
"strategy_ref": "code.contract",
"svg_label": "04",
"code_ref": "doc/card-plan.md:1",
"description": "Useful when only one task may touch device API.",
"evidence": "extension decision."
}
]
}
]
}
}
]
},
{
"title": "Task01 — mutex i PIP",
"order": 90,
"content_kind": "tasks",
"task_refs": [
"task01"
]
}
],
"tasks": {
"task01": {
"title": "Low/Medium/High: ownership i dziedziczenie priorytetu",
"uuid": "2392f81a-ed6c-510b-86b5-06c5e2f1c6aa",
"prompt_tex": "Przejdź po A2, A4, A5, A6, A7 i A8. Odtwórz E01E10 i udowodnij, że task średni nie wyprzedza właściciela z odziedziczonym p3.",
"criterion": "PASS; Low 1→3→1; Medium eReady i started=0 podczas dziedziczenia; High E07 przed Medium E08; digest jest deterministyczny.",
"conclusion_tex": "Mutex rozwiązuje bounded priority inversion przez tymczasowe podniesienie efektywnego priorytetu właściciela. Give może uruchomić High wewnątrz API, zanim kod Low wykona następną instrukcję.",
"flow": [
{
"kind": "block",
"id": "predict",
"title": "A — kontrakt i przewidywanie",
"content_tex": "Rozpisz owner, wait list i priorytety p1/p2/p3.",
"steps": [
{
"id": "order",
"title": "Przewidź E03E08.",
"content_tex": "Wskaż, kiedy Medium może wykonać pierwszą instrukcję."
},
{
"id": "api",
"title": "Odrzuć fałszywe zamienniki.",
"content_tex": "Wyjaśnij, dlaczego semafor binarny i vTaskPrioritySet nie dowodzą PIP."
}
]
},
{
"kind": "block",
"id": "replay",
"title": "B — replay Hazard3",
"content_tex": "Każdy RUN zaczyna się od czystej RAM.",
"steps": [
{
"id": "inherit",
"title": "Zbadaj E02E05.",
"content_tex": "Porównaj holder, priority, eReady i started."
},
{
"id": "handoff",
"title": "Zbadaj E06E09.",
"content_tex": "Sprawdź High-before-Medium i przywrócenie p1."
},
{
"id": "pass",
"title": "Zbadaj E10.",
"content_tex": "Zapisz PASS, trzy SP i digest."
}
]
},
{
"kind": "exercise",
"id": "lock-order",
"title": "Ćwiczenie — dwie blokady",
"prompt_tex": "Dodaj drugi zasób wyłącznie do modelu projektowego. Utwórz tabelę globalnego lock order, która usuwa cykl oczekiwania, i wskaż maksymalny czas trzymania obu mutexów.",
"evidence_tex": "Diagram A8, tabela lock order i kontrprzykład z cyklem.",
"criterion": "Porządek jest globalny, acykliczny i nie obejmuje nieograniczonej operacji.",
"based_on": [
"predict",
"replay"
]
}
],
"educational_requirement_refs": [
"FC08.WE01"
],
"learning_effect_refs": [
"FC08.EN01",
"FC08.EK01"
],
"assessment_criterion_ref": "FC08.KW01"
}
},
"tasks_order": [
"task01"
]
}