1221 lines
40 KiB
JSON
1221 lines
40 KiB
JSON
{
|
||
"$schema": "../../../tools/card-layouts/schemas/card-source.schema.json",
|
||
"schema": "esc-card-source.v1",
|
||
"card": {
|
||
"id": "mpabi-freertos-c-11-static-allocation",
|
||
"series": "freertos-c",
|
||
"series_title": "FreeRTOS C",
|
||
"number": "11",
|
||
"count": "15",
|
||
"slug": "static-allocation",
|
||
"title": "Static and dynamic allocation",
|
||
"topic": "task, queue and timer with two storage policies",
|
||
"project": "Freestanding C nad FreeRTOS",
|
||
"subject": "Informatyka",
|
||
"level": "Rok 2 · L11 · RV32I/Hazard3",
|
||
"revision_date": "2026-07-19T00:00:00+02:00",
|
||
"status": "Gotowa",
|
||
"version": "v00.01",
|
||
"uuid": "33c1da5c-dd20-5ed1-a829-64a5306fc804",
|
||
"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": "ownership boundaries",
|
||
"status": "enabled",
|
||
"target_label": "fig:a1-context"
|
||
},
|
||
{
|
||
"id": "A2",
|
||
"label": "STRUCTURE",
|
||
"subtitle": "dynamic/static object pairs",
|
||
"status": "enabled",
|
||
"target_label": "fig:a2-structure"
|
||
},
|
||
{
|
||
"id": "A3",
|
||
"label": "DISPATCH",
|
||
"subtitle": "same kernel dispatch",
|
||
"status": "unavailable",
|
||
"reason": "Storage policy does not change callback dispatch."
|
||
},
|
||
{
|
||
"id": "A4",
|
||
"label": "APPLICATION",
|
||
"subtitle": "behavior parity",
|
||
"status": "enabled",
|
||
"target_label": "fig:a4-application"
|
||
},
|
||
{
|
||
"id": "A5",
|
||
"label": "FLOW",
|
||
"subtitle": "H0/H1/H2/H3",
|
||
"status": "enabled",
|
||
"target_label": "fig:a5-flow"
|
||
},
|
||
{
|
||
"id": "A6",
|
||
"label": "STATE",
|
||
"subtitle": "covered by flow",
|
||
"status": "unavailable",
|
||
"reason": "No new lifecycle state machine; the card compares storage."
|
||
},
|
||
{
|
||
"id": "A7",
|
||
"label": "RUNTIME",
|
||
"subtitle": "address provenance",
|
||
"status": "enabled",
|
||
"target_label": "fig:a7-runtime"
|
||
},
|
||
{
|
||
"id": "A8",
|
||
"label": "PATTERNS",
|
||
"subtitle": "policy comparison",
|
||
"status": "unavailable",
|
||
"reason": "No wrapper pattern is introduced in this C card."
|
||
}
|
||
],
|
||
"debug_strategies": {
|
||
"code.storage": {
|
||
"id": "code.storage",
|
||
"kind": "code",
|
||
"action": "open",
|
||
"expected_observations": [
|
||
"persistent Static* buffers",
|
||
"application static Idle/timer task memory"
|
||
],
|
||
"assertions": [
|
||
"no local-lifetime storage",
|
||
"both allocation modes enabled"
|
||
],
|
||
"evidence_fields": [
|
||
"symbol",
|
||
"section",
|
||
"code_ref"
|
||
],
|
||
"prerequisites": [
|
||
"FC11 source"
|
||
],
|
||
"layout": [
|
||
"buffers",
|
||
"create APIs",
|
||
"FreeRTOSConfig"
|
||
],
|
||
"commands": [
|
||
"rg -n 'x.*CreateStatic|vApplicationGet.*TaskMemory|Static(Task|Queue|Timer)_t' include src"
|
||
]
|
||
},
|
||
"run.heap": {
|
||
"id": "run.heap",
|
||
"kind": "run",
|
||
"action": "replay",
|
||
"expected_observations": [
|
||
"H1 < H0",
|
||
"H2 == H1",
|
||
"H3 == H2"
|
||
],
|
||
"assertions": [
|
||
"objects alive at H3",
|
||
"no exact delta assumption"
|
||
],
|
||
"evidence_fields": [
|
||
"H0",
|
||
"H1",
|
||
"H2",
|
||
"H3",
|
||
"timestamp"
|
||
],
|
||
"prerequisites": [
|
||
"clean Hazard3 RAM"
|
||
],
|
||
"layout": [
|
||
"heap values",
|
||
"event order"
|
||
],
|
||
"commands": [
|
||
"print g_fc11.heap_h0",
|
||
"print g_fc11.heap_h1",
|
||
"print g_fc11.heap_h2",
|
||
"print g_fc11.heap_h3"
|
||
]
|
||
},
|
||
"run.parity": {
|
||
"id": "run.parity",
|
||
"kind": "run",
|
||
"action": "replay",
|
||
"expected_observations": [
|
||
"both receive 0xCAFE",
|
||
"both timers callback once"
|
||
],
|
||
"assertions": [
|
||
"distinct stacks",
|
||
"PASS and deterministic digest"
|
||
],
|
||
"evidence_fields": [
|
||
"received",
|
||
"timer calls",
|
||
"SP",
|
||
"digest"
|
||
],
|
||
"prerequisites": [
|
||
"scheduler running"
|
||
],
|
||
"layout": [
|
||
"two branches",
|
||
"verifier"
|
||
],
|
||
"commands": [
|
||
"print/x g_fc11.dynamic_received",
|
||
"print/x g_fc11.static_received",
|
||
"print g_fc11_pass"
|
||
]
|
||
}
|
||
},
|
||
"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": "Static and dynamic allocation",
|
||
"url": "https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/f4d7caf3-d665-5a2d-b9eb-39a120a64ff7",
|
||
"repository_url": "https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-c-static-allocation",
|
||
"url_host_uuid": "dce7fb9d-7b2f-5d49-96a2-3a30d3070b84",
|
||
"url_domain": "mpabi.pl",
|
||
"doc_uuid": "f4d7caf3-d665-5a2d-b9eb-39a120a64ff7",
|
||
"revision": "v00.01",
|
||
"issued_on": "2026-07-19T00:00:00+02:00",
|
||
"series": "FREERTOS-C-11",
|
||
"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ń rozdziela semantykę obiektu FreeRTOS od polityki przechowywania i dowodzi jej przez adresy oraz cztery pomiary wolnego heap.",
|
||
"scope_title": "Zakres karty",
|
||
"scope_content_tex": "Dynamiczny i statyczny task, queue oraz timer wykonują ten sam eksperyment. H1 jest mniejsze od H0, H2 równa się H1, a H3 równa się H2. Pamięć Idle i timer-service dostarcza aplikacja.",
|
||
"scope_table": {
|
||
"headers": [
|
||
"Lekcja",
|
||
"Task",
|
||
"Najważniejsza idea",
|
||
"Priorytet",
|
||
"Status",
|
||
"Version"
|
||
],
|
||
"rows": [
|
||
{
|
||
"chapter": "FC11",
|
||
"task": "Task01",
|
||
"idea_tex": "task, queue and timer with two storage policies",
|
||
"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": {
|
||
"FC11.EN01": {
|
||
"bloom_level": "Analiza",
|
||
"label": "Storage ownership",
|
||
"text": "Uczeń rozdziela semantykę obiektu i politykę przechowywania.",
|
||
"assessment_criteria": [
|
||
"FC11.KW01"
|
||
]
|
||
},
|
||
"FC11.EK01": {
|
||
"bloom_level": "Zastosowanie",
|
||
"label": "Heap replay",
|
||
"text": "Uczeń odtwarza E01–E08 i dowodzi H1<H0, H2=H1, H3=H2.",
|
||
"assessment_criteria": [
|
||
"FC11.KW01"
|
||
]
|
||
}
|
||
},
|
||
"assessment_criteria": {
|
||
"FC11.KW01": {
|
||
"text": "PASS; address provenance; message and callback parity; deterministic digest.",
|
||
"learning_effects": [
|
||
"FC11.EN01",
|
||
"FC11.EK01"
|
||
]
|
||
}
|
||
},
|
||
"educational_requirements": {
|
||
"FC11.WE01": {
|
||
"text": "Porównanie dynamicznej i statycznej polityki pamięci obiektów FreeRTOS.",
|
||
"label": "task, queue and timer with two storage policies",
|
||
"learning_effects": [
|
||
"FC11.EN01",
|
||
"FC11.EK01"
|
||
],
|
||
"learning_tree": {
|
||
"schema": "we-learning-tree.v1",
|
||
"policy": "Każda aktywna kotwica wskazuje kod lub checkpoint.",
|
||
"ogolne": [
|
||
{
|
||
"effect_ref": "FC11.EN01",
|
||
"display": "EN LOCAL RTOS.11",
|
||
"source": "LOCAL",
|
||
"official": "RTOS",
|
||
"local": "11",
|
||
"kind": "EN",
|
||
"tree_id": "FC11.WE01.OG.LOCAL.RTOS.11",
|
||
"text": "Uczeń rozdziela semantykę obiektu i politykę przechowywania.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "FC11.KW01",
|
||
"display": "KW LOCAL RTOS.11",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "RTOS",
|
||
"local": "11",
|
||
"text": "Łączy kod, diagram i zweryfikowany dowód."
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"zawodowe": [
|
||
{
|
||
"effect_ref": "FC11.EK01",
|
||
"display": "EK LOCAL RTOS.11",
|
||
"source": "LOCAL",
|
||
"official": "RTOS",
|
||
"local": "11",
|
||
"kind": "EK",
|
||
"tree_id": "FC11.WE01.TECH.LOCAL.RTOS.11",
|
||
"text": "Uczeń odtwarza E01–E08 i dowodzi H1<H0, H2=H1, H3=H2.",
|
||
"kw": [
|
||
{
|
||
"criterion_ref": "FC11.KW01",
|
||
"display": "KW LOCAL RTOS.11",
|
||
"source": "LOCAL",
|
||
"kind": "KW",
|
||
"official": "RTOS",
|
||
"local": "11",
|
||
"text": "Łączy kod, diagram i zweryfikowany dowód."
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"debug_checkpoints": {
|
||
"schema": "stem-debug-checkpoints.v1",
|
||
"semantics": "deterministic-replay",
|
||
"artifact": {
|
||
"source": "src/tasks/task01_static_allocation.c",
|
||
"source_git_blob": "a0cacf0b28af629cd7f68173082bf9ecf3e21213",
|
||
"elf": "build/task01_static_allocation/prog.elf",
|
||
"hazard3_elf_sha256": "be1db213d76dfc05b4602910fe2947926ef0d41d516c71df4bc8081ac35eee42",
|
||
"hazard3_image": "build/task01_static_allocation/prog.bin",
|
||
"hazard3_image_sha256": "ed981d6c22b1c8ca55fcc3e848a3c2459ec88c8221d7c7eda0880fbcd2413b6a"
|
||
},
|
||
"targets": {
|
||
"hazard3-sim": {
|
||
"adapter": "hazard3-reset-load-replay.v1",
|
||
"baseline": "restart-backend",
|
||
"clean_ram": true
|
||
}
|
||
},
|
||
"items": {
|
||
"task01.h0": {
|
||
"event_id": "E01",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 1"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11_event_count",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.h1": {
|
||
"event_id": "E02",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 2"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11.heap_h1 < g_fc11.heap_h0",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.h2": {
|
||
"event_id": "E03",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 3"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11.heap_h2 == g_fc11.heap_h1",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.dynamic-run": {
|
||
"event_id": "E04",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 4"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11.dynamic_received",
|
||
"equals": 51966
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.static-run": {
|
||
"event_id": "E05",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 5"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11.static_received",
|
||
"equals": 51966
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.dynamic-callback": {
|
||
"event_id": "E06",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 6"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11.dynamic_timer_calls",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.static-callback": {
|
||
"event_id": "E07",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 7"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11.static_timer_calls",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"task01.pass": {
|
||
"event_id": "E08",
|
||
"stop": {
|
||
"symbol": "fc11_checkpoint_committed",
|
||
"offset": 0,
|
||
"condition": "$a0 == 8"
|
||
},
|
||
"verify": {
|
||
"expressions": [
|
||
{
|
||
"expr": "g_fc11_pass",
|
||
"equals": 1
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"sections": [
|
||
{
|
||
"title": "A1 — Context",
|
||
"order": 10,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Application, kernel and RAM responsibilities are explicit.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a1-context.png",
|
||
"html_path": "assets/a1-context.svg",
|
||
"source_path": "assets/a1-context.puml",
|
||
"caption": "A1 CONTEXT — ownership boundaries.",
|
||
"label": "fig:a1-context",
|
||
"alt": "ownership boundaries",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"application": 1,
|
||
"dynamic": 1,
|
||
"static": 1,
|
||
"kernel": 1,
|
||
"ram": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc11-a1-context",
|
||
"title": "A1 · ownership boundaries",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · two storage policies"
|
||
},
|
||
"block": {
|
||
"id": "a1",
|
||
"label": "A1 CONTEXT",
|
||
"description": "Application, kernel and RAM responsibilities are explicit."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "context",
|
||
"label": "OWNERSHIP BOUNDARIES",
|
||
"steps": [
|
||
{
|
||
"id": "application",
|
||
"number": 1,
|
||
"label": "application owns experiment",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:20",
|
||
"description": "application owns experiment",
|
||
"evidence": "global experiment"
|
||
},
|
||
{
|
||
"id": "dynamic",
|
||
"number": 2,
|
||
"label": "dynamic APIs request storage",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:218",
|
||
"description": "dynamic APIs request storage",
|
||
"evidence": "xTaskCreate/xQueueCreate/xTimerCreate"
|
||
},
|
||
{
|
||
"id": "static",
|
||
"number": 3,
|
||
"label": "static APIs receive storage",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:239",
|
||
"description": "static APIs receive storage",
|
||
"evidence": "named buffers"
|
||
},
|
||
{
|
||
"id": "kernel",
|
||
"number": 4,
|
||
"label": "kernel owns object semantics",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "04",
|
||
"code_ref": "vendor/FreeRTOS-Kernel/tasks.c:1",
|
||
"description": "kernel owns object semantics",
|
||
"evidence": "same scheduler"
|
||
},
|
||
{
|
||
"id": "ram",
|
||
"number": 5,
|
||
"label": "both policies coexist in RAM",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:26",
|
||
"description": "both policies coexist in RAM",
|
||
"evidence": "ucHeap plus static buffers"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A2 — Structure",
|
||
"order": 20,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "landscape",
|
||
"content_tex": "Task, queue and timer are compared pairwise.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a2-structure.png",
|
||
"html_path": "assets/a2-structure.svg",
|
||
"source_path": "assets/a2-structure.puml",
|
||
"caption": "A2 STRUCTURE — object pairs.",
|
||
"label": "fig:a2-structure",
|
||
"alt": "object pairs",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 940,
|
||
"page_height": 560,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"dynamic-task": 1,
|
||
"static-task": 1,
|
||
"dynamic-queue": 1,
|
||
"static-queue": 1,
|
||
"dynamic-timer": 1,
|
||
"static-timer": 1,
|
||
"services": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc11-a2-structure",
|
||
"title": "A2 · object pairs",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · two storage policies"
|
||
},
|
||
"block": {
|
||
"id": "a2",
|
||
"label": "A2 STRUCTURE",
|
||
"description": "Task, queue and timer are compared pairwise."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "structure",
|
||
"label": "OBJECT PAIRS",
|
||
"steps": [
|
||
{
|
||
"id": "dynamic-task",
|
||
"number": 1,
|
||
"label": "dynamic task handle is in heap",
|
||
"mode": "RUN",
|
||
"event_id": "E02",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:218",
|
||
"snapshot_ref": "task01.h1",
|
||
"description": "dynamic task handle is in heap",
|
||
"evidence": "heap address"
|
||
},
|
||
{
|
||
"id": "static-task",
|
||
"number": 2,
|
||
"label": "static task uses TCB and stack buffers",
|
||
"mode": "RUN",
|
||
"event_id": "E03",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:239",
|
||
"snapshot_ref": "task01.h2",
|
||
"description": "static task uses TCB and stack buffers",
|
||
"evidence": "outside heap"
|
||
},
|
||
{
|
||
"id": "dynamic-queue",
|
||
"number": 3,
|
||
"label": "dynamic queue object is in heap",
|
||
"mode": "RUN",
|
||
"event_id": "E02",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:228",
|
||
"snapshot_ref": "task01.h1",
|
||
"description": "dynamic queue object is in heap",
|
||
"evidence": "heap address"
|
||
},
|
||
{
|
||
"id": "static-queue",
|
||
"number": 4,
|
||
"label": "static queue uses supplied storage",
|
||
"mode": "RUN",
|
||
"event_id": "E03",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "04",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:247",
|
||
"snapshot_ref": "task01.h2",
|
||
"description": "static queue uses supplied storage",
|
||
"evidence": "outside heap"
|
||
},
|
||
{
|
||
"id": "dynamic-timer",
|
||
"number": 5,
|
||
"label": "dynamic timer object is in heap",
|
||
"mode": "RUN",
|
||
"event_id": "E02",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:229",
|
||
"snapshot_ref": "task01.h1",
|
||
"description": "dynamic timer object is in heap",
|
||
"evidence": "heap address"
|
||
},
|
||
{
|
||
"id": "static-timer",
|
||
"number": 6,
|
||
"label": "static timer uses StaticTimer_t",
|
||
"mode": "RUN",
|
||
"event_id": "E03",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "06",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:250",
|
||
"snapshot_ref": "task01.h2",
|
||
"description": "static timer uses StaticTimer_t",
|
||
"evidence": "outside heap"
|
||
},
|
||
{
|
||
"id": "services",
|
||
"number": 7,
|
||
"label": "Idle and timer-service storage is static",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "07",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:45",
|
||
"description": "Idle and timer-service storage is static",
|
||
"evidence": "two application callbacks"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A4 — Application",
|
||
"order": 40,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Storage differs while application behavior remains equal.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a4-application.png",
|
||
"html_path": "assets/a4-application.svg",
|
||
"source_path": "assets/a4-application.puml",
|
||
"caption": "A4 APPLICATION — behavior parity.",
|
||
"label": "fig:a4-application",
|
||
"alt": "behavior parity",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"dynamic-worker": 1,
|
||
"static-worker": 1,
|
||
"daemon": 1,
|
||
"verifier": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc11-a4-application",
|
||
"title": "A4 · behavior parity",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · two storage policies"
|
||
},
|
||
"block": {
|
||
"id": "a4",
|
||
"label": "A4 APPLICATION",
|
||
"description": "Storage differs while application behavior remains equal."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "application",
|
||
"label": "BEHAVIOR PARITY",
|
||
"steps": [
|
||
{
|
||
"id": "dynamic-worker",
|
||
"number": 1,
|
||
"label": "dynamic branch receives message",
|
||
"mode": "RUN",
|
||
"event_id": "E04",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:121",
|
||
"snapshot_ref": "task01.dynamic-run",
|
||
"description": "dynamic branch receives message",
|
||
"evidence": "0xCAFE"
|
||
},
|
||
{
|
||
"id": "static-worker",
|
||
"number": 2,
|
||
"label": "static branch receives message",
|
||
"mode": "RUN",
|
||
"event_id": "E05",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:139",
|
||
"snapshot_ref": "task01.static-run",
|
||
"description": "static branch receives message",
|
||
"evidence": "0xCAFE"
|
||
},
|
||
{
|
||
"id": "daemon",
|
||
"number": 3,
|
||
"label": "daemon executes both callbacks",
|
||
"mode": "RUN",
|
||
"event_id": "E07",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:99",
|
||
"snapshot_ref": "task01.static-callback",
|
||
"description": "daemon executes both callbacks",
|
||
"evidence": "1 + 1"
|
||
},
|
||
{
|
||
"id": "verifier",
|
||
"number": 4,
|
||
"label": "verifier checks behavior parity",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "04",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:157",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "verifier checks behavior parity",
|
||
"evidence": "PASS"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A5 — Flow",
|
||
"order": 50,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "landscape",
|
||
"content_tex": "H0/H1/H2/H3 bracket creation and scheduler startup.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a5-flow.png",
|
||
"html_path": "assets/a5-flow.svg",
|
||
"source_path": "assets/a5-flow.puml",
|
||
"caption": "A5 FLOW — four heap checkpoints.",
|
||
"label": "fig:a5-flow",
|
||
"alt": "four heap checkpoints",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 940,
|
||
"page_height": 560,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"h0": 1,
|
||
"h1": 1,
|
||
"h2": 1,
|
||
"dynamic-run": 1,
|
||
"static-run": 1,
|
||
"dynamic-callback": 1,
|
||
"static-callback": 1,
|
||
"pass": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-sequence",
|
||
"storage_key": "fc11-a5-flow",
|
||
"title": "A5 · four heap checkpoints",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · two storage policies"
|
||
},
|
||
"block": {
|
||
"id": "a5",
|
||
"label": "A5 FLOW",
|
||
"description": "H0/H1/H2/H3 bracket creation and scheduler startup."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "flow",
|
||
"label": "FOUR HEAP CHECKPOINTS",
|
||
"steps": [
|
||
{
|
||
"id": "h0",
|
||
"number": 1,
|
||
"label": "H0 baseline",
|
||
"mode": "RUN",
|
||
"event_id": "E01",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:214",
|
||
"snapshot_ref": "task01.h0",
|
||
"description": "H0 baseline",
|
||
"evidence": "baseline"
|
||
},
|
||
{
|
||
"id": "h1",
|
||
"number": 2,
|
||
"label": "dynamic objects make H1 smaller",
|
||
"mode": "RUN",
|
||
"event_id": "E02",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:236",
|
||
"snapshot_ref": "task01.h1",
|
||
"description": "dynamic objects make H1 smaller",
|
||
"evidence": "H1 < H0"
|
||
},
|
||
{
|
||
"id": "h2",
|
||
"number": 3,
|
||
"label": "static objects leave heap unchanged",
|
||
"mode": "RUN",
|
||
"event_id": "E03",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:263",
|
||
"snapshot_ref": "task01.h2",
|
||
"description": "static objects leave heap unchanged",
|
||
"evidence": "H2 = H1"
|
||
},
|
||
{
|
||
"id": "dynamic-run",
|
||
"number": 4,
|
||
"label": "dynamic worker runs",
|
||
"mode": "RUN",
|
||
"event_id": "E04",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "04",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:121",
|
||
"snapshot_ref": "task01.dynamic-run",
|
||
"description": "dynamic worker runs",
|
||
"evidence": "message"
|
||
},
|
||
{
|
||
"id": "static-run",
|
||
"number": 5,
|
||
"label": "static worker runs",
|
||
"mode": "RUN",
|
||
"event_id": "E05",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:139",
|
||
"snapshot_ref": "task01.static-run",
|
||
"description": "static worker runs",
|
||
"evidence": "message"
|
||
},
|
||
{
|
||
"id": "dynamic-callback",
|
||
"number": 6,
|
||
"label": "dynamic timer callback",
|
||
"mode": "RUN",
|
||
"event_id": "E06",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "06",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:99",
|
||
"snapshot_ref": "task01.dynamic-callback",
|
||
"description": "dynamic timer callback",
|
||
"evidence": "count 1"
|
||
},
|
||
{
|
||
"id": "static-callback",
|
||
"number": 7,
|
||
"label": "static timer callback",
|
||
"mode": "RUN",
|
||
"event_id": "E07",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "07",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:99",
|
||
"snapshot_ref": "task01.static-callback",
|
||
"description": "static timer callback",
|
||
"evidence": "count 1"
|
||
},
|
||
{
|
||
"id": "pass",
|
||
"number": 8,
|
||
"label": "H3 unchanged and verifier passes",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "08",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:157",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "H3 unchanged and verifier passes",
|
||
"evidence": "H3 = H2"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "A7 — Runtime",
|
||
"order": 70,
|
||
"content_kind": "prose",
|
||
"asset_page_mode": "one-per-page",
|
||
"page_orientation": "portrait",
|
||
"content_tex": "Debugger evidence connects handles to heap or named buffers.",
|
||
"assets": [
|
||
{
|
||
"path": "assets/a7-runtime.png",
|
||
"html_path": "assets/a7-runtime.svg",
|
||
"source_path": "assets/a7-runtime.puml",
|
||
"caption": "A7 RUNTIME — address provenance.",
|
||
"label": "fig:a7-runtime",
|
||
"alt": "address provenance",
|
||
"kind": "diagram",
|
||
"width": 1.0,
|
||
"page_grid": {
|
||
"columns": 1,
|
||
"rows": 1,
|
||
"page_width": 660,
|
||
"page_height": 760,
|
||
"overview": true,
|
||
"step_tiles": {
|
||
"heap-arena": 1,
|
||
"named-buffers": 1,
|
||
"service-buffers": 1,
|
||
"heap-relation": 1,
|
||
"evidence": 1
|
||
}
|
||
},
|
||
"interactive": {
|
||
"kind": "uml-class",
|
||
"storage_key": "fc11-a7-runtime",
|
||
"title": "A7 · address provenance",
|
||
"task": {
|
||
"id": "task01",
|
||
"label": "Task01 · two storage policies"
|
||
},
|
||
"block": {
|
||
"id": "a7",
|
||
"label": "A7 RUNTIME",
|
||
"description": "Debugger evidence connects handles to heap or named buffers."
|
||
},
|
||
"phases": [
|
||
{
|
||
"id": "runtime",
|
||
"label": "ADDRESS PROVENANCE",
|
||
"steps": [
|
||
{
|
||
"id": "heap-arena",
|
||
"number": 1,
|
||
"label": "dynamic handles lie in ucHeap",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "01",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:174",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "dynamic handles lie in ucHeap",
|
||
"evidence": "three true predicates"
|
||
},
|
||
{
|
||
"id": "named-buffers",
|
||
"number": 2,
|
||
"label": "static handles lie outside ucHeap",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "02",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:177",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "static handles lie outside ucHeap",
|
||
"evidence": "three false predicates"
|
||
},
|
||
{
|
||
"id": "service-buffers",
|
||
"number": 3,
|
||
"label": "kernel-service buffers are named",
|
||
"mode": "CODE",
|
||
"strategy_ref": "code.storage",
|
||
"svg_label": "03",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:34",
|
||
"description": "kernel-service buffers are named",
|
||
"evidence": "Idle and daemon buffers"
|
||
},
|
||
{
|
||
"id": "heap-relation",
|
||
"number": 4,
|
||
"label": "four checkpoints satisfy relation",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.heap",
|
||
"svg_label": "04",
|
||
"code_ref": "include/task01_static_allocation_model.h:34",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "four checkpoints satisfy relation",
|
||
"evidence": "H1<H0; H2=H1; H3=H2"
|
||
},
|
||
{
|
||
"id": "evidence",
|
||
"number": 5,
|
||
"label": "commit-last evidence is deterministic",
|
||
"mode": "RUN",
|
||
"event_id": "E08",
|
||
"strategy_ref": "run.parity",
|
||
"svg_label": "05",
|
||
"code_ref": "src/tasks/task01_static_allocation.c:72",
|
||
"snapshot_ref": "task01.pass",
|
||
"description": "commit-last evidence is deterministic",
|
||
"evidence": "cdf44a0a"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"title": "Task01 — two storage policies",
|
||
"order": 90,
|
||
"content_kind": "tasks",
|
||
"task_refs": [
|
||
"task01"
|
||
]
|
||
}
|
||
],
|
||
"tasks": {
|
||
"task01": {
|
||
"title": "Same behavior, two storage policies",
|
||
"uuid": "f4d7caf3-d665-5a2d-b9eb-39a120a64ff7",
|
||
"prompt_tex": "Przejdź po A1, A2, A4, A5 i A7. Odtwórz E01–E08 oraz udowodnij relacje H1<H0, H2=H1 i H3=H2.",
|
||
"criterion": "PASS; address provenance; message and callback parity; deterministic digest.",
|
||
"conclusion_tex": "Statyczne API zmienia własność pamięci, ale nie semantykę taska, kolejki ani timera.",
|
||
"flow": [
|
||
{
|
||
"kind": "block",
|
||
"id": "predict",
|
||
"title": "A — przewidywanie",
|
||
"content_tex": "Przewidź cztery pomiary heap.",
|
||
"steps": [
|
||
{
|
||
"id": "relation",
|
||
"title": "Zapisz relacje H0–H3.",
|
||
"content_tex": "Nie zakładaj dokładnej liczby bajtów."
|
||
},
|
||
{
|
||
"id": "ownership",
|
||
"title": "Wskaż właściciela pamięci.",
|
||
"content_tex": "Rozdziel ucHeap i named buffers."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"kind": "block",
|
||
"id": "replay",
|
||
"title": "B — replay Hazard3",
|
||
"content_tex": "Wykonaj E01–E08 z clean RAM.",
|
||
"steps": [
|
||
{
|
||
"id": "heap",
|
||
"title": "Zbadaj H0/H1/H2/H3.",
|
||
"content_tex": "Zapisz wartości i relacje."
|
||
},
|
||
{
|
||
"id": "parity",
|
||
"title": "Zbadaj obie gałęzie.",
|
||
"content_tex": "Porównaj message, timer callback i stack."
|
||
},
|
||
{
|
||
"id": "pass",
|
||
"title": "Zbadaj E08.",
|
||
"content_tex": "Zapisz PASS, digest i timestamp."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"kind": "exercise",
|
||
"id": "choose-policy",
|
||
"title": "Ćwiczenie — wybór polityki",
|
||
"prompt_tex": "Dla taska okresowego, kolejki telemetrycznej i timera bezpieczeństwa wybierz dynamiczne albo statyczne tworzenie. Uzasadnij lifetime i ownership.",
|
||
"evidence_tex": "Tabela obiekt→API→storage→lifetime oraz ślad H0–H3.",
|
||
"criterion": "Każdy bufor ma trwałość co najmniej tak długą jak obiekt kernelowy.",
|
||
"based_on": [
|
||
"predict",
|
||
"replay"
|
||
]
|
||
}
|
||
],
|
||
"educational_requirement_refs": [
|
||
"FC11.WE01"
|
||
],
|
||
"learning_effect_refs": [
|
||
"FC11.EN01",
|
||
"FC11.EK01"
|
||
],
|
||
"assessment_criterion_ref": "FC11.KW01"
|
||
}
|
||
},
|
||
"tasks_order": [
|
||
"task01"
|
||
]
|
||
}
|