13 Commits

Author SHA1 Message Date
user 10a8be72e3 chore: preserve current FreeRTOS and C card updates 2026-07-21 19:14:19 +02:00
user 4785d506fc docs: render FC01 heap4 PDF [skip actions] 2026-07-20 12:08:06 +02:00
user 48eccb5e24 feat: add interactive FC01 heap4 card 2026-07-20 12:04:14 +02:00
user bd34c7ec1e docs: render heap4 PDF for 2b17bb4ff9 [skip actions] 2026-07-14 23:28:28 +02:00
user 2b17bb4ff9 feat: rebuild heap4 card around upstream FreeRTOS allocator 2026-07-14 23:27:13 +02:00
mpabi 032a06fdef docs: checkpoint heap4 card audit 2026-07-14 20:00:00 +02:00
mpabi 8aee0b104c Add rendered PDF [skip actions] 2026-07-14 19:15:59 +02:00
mpabi 49cabf2077 Document FreeRTOS Book v1.1.0 mapping 2026-07-14 19:15:20 +02:00
gitea-actions ef1854cfa0 Render lab-rv32i-freertos-heap4 PDF for a40d2916df [skip actions] 2026-05-07 17:51:29 +00:00
mpabi a40d2916df Document tasks branch namespace 2026-05-07 19:43:33 +02:00
mpabi d589bb8c41 Add rendered PDF [skip actions] 2026-05-02 01:09:48 +02:00
mpabi f4973842ad Clarify heap buffer placement 2026-05-02 01:09:38 +02:00
mpabi 62fb0f8849 Add rendered PDF [skip actions] 2026-05-02 01:06:11 +02:00
81 changed files with 10414 additions and 2076 deletions
+13 -13
View File
@@ -1,18 +1,18 @@
*.aux
*.log
*.out
*.fls
*.fdb_latexmk
*.synctex.gz
*.pdf
build-meta.tex
.rv/
.nvim/
.vim/
.build/
.gdb_history
.stem/
host-build/
build/*/prog.bin
build/*/prog.elf
build/*/prog.lst
build/*/prog.map
build/*/*.o
cmake-build-*/
compile_commands.json
doc/generated/*.aux
doc/generated/*.fdb_latexmk
doc/generated/*.fls
doc/generated/*.log
doc/generated/*.out
doc/generated/*.pdf
doc/generated/*.upa
doc/generated/*.upb
doc/generated/build-meta.tex
+114
View File
@@ -0,0 +1,114 @@
cmake_minimum_required(VERSION 3.13)
if(NOT PICO_SDK_PATH)
if(DEFINED ENV{PICO_SDK_PATH})
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
else()
message(FATAL_ERROR "Set PICO_SDK_PATH to a Raspberry Pi Pico SDK checkout")
endif()
endif()
include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(freertos_heap4_rp2350 C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
# The card and allocator are C-only. Debian's compact RISC-V toolchain does
# not ship libstdc++ headers, so keep the SDK's optional new/delete source out
# while preserving the interface targets expected by pico_stdlib.
add_library(pico_cxx_options_headers INTERFACE)
target_include_directories(pico_cxx_options_headers SYSTEM INTERFACE
${PICO_SDK_PATH}/src/rp2_common/pico_cxx_options/include)
add_library(pico_cxx_options INTERFACE)
target_link_libraries(pico_cxx_options INTERFACE pico_cxx_options_headers)
pico_sdk_init()
if(NOT PICO_PLATFORM STREQUAL "rp2350-riscv")
message(FATAL_ERROR "This card targets the RP2350 RISC-V cores")
endif()
if(NOT HEAP4_UPSTREAM_ROOT)
if(DEFINED ENV{HEAP4_UPSTREAM_ROOT})
set(HEAP4_UPSTREAM_ROOT $ENV{HEAP4_UPSTREAM_ROOT})
else()
set(HEAP4_UPSTREAM_ROOT /opt/FreeRTOS-Kernel)
endif()
endif()
if(NOT EXISTS ${HEAP4_UPSTREAM_ROOT}/portable/MemMang/heap_4.c)
message(FATAL_ERROR "Pinned FreeRTOS heap_4.c not found at ${HEAP4_UPSTREAM_ROOT}")
endif()
if(NOT FREERTOS_RP2350_PATH)
if(DEFINED ENV{FREERTOS_RP2350_PATH})
set(FREERTOS_RP2350_PATH $ENV{FREERTOS_RP2350_PATH})
else()
set(FREERTOS_RP2350_PATH /opt/FreeRTOS-RP2350)
endif()
endif()
if(NOT EXISTS ${FREERTOS_RP2350_PATH}/portable/ThirdParty/GCC/RP2350_RISC-V/portASM.S)
message(FATAL_ERROR "Compatible RP2350 FreeRTOS core/port not found at ${FREERTOS_RP2350_PATH}")
endif()
set(FREERTOS_CONFIG_FILE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include)
# Raspberry Pi's port CMake uses FREERTOS_KERNEL_PATH for its matching core.
# Keep the stable allocator root separate and add its heap_4.c explicitly.
set(FREERTOS_KERNEL_PATH ${FREERTOS_RP2350_PATH})
add_subdirectory(
${FREERTOS_RP2350_PATH}/portable/ThirdParty/GCC/RP2350_RISC-V
${CMAKE_BINARY_DIR}/freertos-kernel)
set(HEAP4_PROFILE "observe" CACHE STRING "observe, debug or release")
set_property(CACHE HEAP4_PROFILE PROPERTY STRINGS observe debug release)
set(HEAP4_BINARY_TYPE "no_flash" CACHE STRING "Pico SDK binary type")
set_property(CACHE HEAP4_BINARY_TYPE PROPERTY STRINGS no_flash default)
if(HEAP4_PROFILE STREQUAL "observe")
set(HEAP4_COMPILE_OPTIONS
-O0 -g3 -fno-omit-frame-pointer -fno-inline
-fno-optimize-sibling-calls)
elseif(HEAP4_PROFILE STREQUAL "debug")
set(HEAP4_COMPILE_OPTIONS
-Og -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls)
elseif(HEAP4_PROFILE STREQUAL "release")
set(HEAP4_COMPILE_OPTIONS -O2)
else()
message(FATAL_ERROR "HEAP4_PROFILE must be observe, debug or release")
endif()
set(MODEL_TASKS
task01_first_fit_split
task02_address_order_coalesce)
foreach(task IN LISTS MODEL_TASKS)
set(task_source src/tasks/${task}.c)
add_executable(${task} ${task_source})
target_include_directories(${task} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tasks)
set_property(SOURCE ${task_source} APPEND PROPERTY COMPILE_OPTIONS
${HEAP4_COMPILE_OPTIONS} -Wall -Wextra -Wpedantic)
target_link_libraries(${task} pico_stdlib)
pico_enable_stdio_usb(${task} 0)
pico_enable_stdio_uart(${task} 0)
if(NOT HEAP4_BINARY_TYPE STREQUAL "default")
pico_set_binary_type(${task} ${HEAP4_BINARY_TYPE})
endif()
pico_add_extra_outputs(${task})
endforeach()
set(heap4_task task03_freertos_heap4)
set(heap4_source src/tasks/${heap4_task}.c)
add_executable(${heap4_task} ${heap4_source})
target_sources(${heap4_task} PRIVATE
${HEAP4_UPSTREAM_ROOT}/portable/MemMang/heap_4.c)
target_include_directories(${heap4_task} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_CURRENT_LIST_DIR}/src/tasks)
set_property(SOURCE ${heap4_source} APPEND PROPERTY COMPILE_OPTIONS
${HEAP4_COMPILE_OPTIONS} -Wall -Wextra -Wpedantic)
target_link_libraries(${heap4_task} pico_stdlib FreeRTOS-Kernel)
pico_enable_stdio_usb(${heap4_task} 0)
pico_enable_stdio_uart(${heap4_task} 0)
if(NOT HEAP4_BINARY_TYPE STREQUAL "default")
pico_set_binary_type(${heap4_task} ${HEAP4_BINARY_TYPE})
endif()
pico_add_extra_outputs(${heap4_task})
+70 -52
View File
@@ -6,11 +6,18 @@ OBJDUMP := $(RISCV_PREFIX)objdump
SIZE := $(RISCV_PREFIX)size
HOST_CC ?= cc
DEBUG ?= 1
ifeq ($(DEBUG),1)
PROFILE ?= observe
ifeq ($(PROFILE),observe)
OPTFLAGS := -O0 -fno-omit-frame-pointer -fno-inline -fno-optimize-sibling-calls
DBGFLAGS := -g3 -ggdb
else
else ifeq ($(PROFILE),debug)
OPTFLAGS := -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls
DBGFLAGS := -g3 -ggdb
else ifeq ($(PROFILE),release)
OPTFLAGS := -O2
DBGFLAGS :=
else
$(error PROFILE must be observe, debug or release)
endif
RV_ENV_ROOT ?= /opt/rv-env
@@ -21,36 +28,35 @@ LDSCRIPT ?= $(H3_COMMON)/link_hazard3.ld
LAB_RUNTIME_DIR ?= $(RV_ENV_ROOT)/vendor/lab-runtime
MEMOPS ?= $(LAB_RUNTIME_DIR)/memops.c
LOCAL_FREERTOS := $(abspath ../lab-rv32i-freertos-task-stack-vector/vendor/FreeRTOS-Kernel)
FREERTOS_KERNEL_PATH ?= $(if $(wildcard /opt/FreeRTOS-Kernel/include/FreeRTOS.h),/opt/FreeRTOS-Kernel,$(LOCAL_FREERTOS))
FREERTOS_PORT := $(FREERTOS_KERNEL_PATH)/portable/GCC/RISC-V
HEAP4_SOURCE := $(FREERTOS_KERNEL_PATH)/portable/MemMang/heap_4.c
BUILD_ROOT ?= build
HOST_BUILD_ROOT ?= host-build
TASKS := \
task01_heap_map \
task02_free_list \
task03_heap_init \
task04_alignment \
task05_malloc_first_fit \
task06_split_block \
task07_free_insert \
task08_coalescing \
task09_config_macros \
task10_heap4_demo
task01_first_fit_split \
task02_address_order_coalesce \
task03_freertos_heap4
ARCH ?= rv32i_zicsr_zifencei
ABI ?= ilp32
COMMON_FLAGS := -std=c99 -march=$(ARCH) -mabi=$(ABI) -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-stack-protector $(DBGFLAGS) -Wall -Wextra -Isrc/tasks
LINK_FLAGS := -Wl,--no-relax -Wl,-T,$(LDSCRIPT)
COMMON_FLAGS := -std=c11 -march=$(ARCH) -mabi=$(ABI) -nostdlib -nostartfiles \
-ffreestanding -fno-builtin -fno-stack-protector -ffunction-sections \
-fdata-sections $(OPTFLAGS) $(DBGFLAGS) -Wall -Wextra -Wpedantic
MODEL_CPPFLAGS := -Isrc/tasks
KERNEL_CPPFLAGS := -Iinclude/freestanding -Iinclude -Isrc/tasks \
-I$(FREERTOS_KERNEL_PATH)/include -I$(FREERTOS_PORT)
LINK_FLAGS := -Wl,--no-relax -Wl,--gc-sections -T $(LDSCRIPT)
LIBS := -lgcc
EMIT_FLAGS := -std=c99 -march=$(ARCH) -mabi=$(ABI) -O -ffreestanding -fno-builtin -fno-stack-protector -nostdlib -nostartfiles -Wall -Wextra -Isrc/tasks
CFLAGS_STEP := $(COMMON_FLAGS) -O
HOST_CFLAGS := -std=c99 -O0 -g -Wall -Wextra -DHOST_PRINTF=1 -Isrc/tasks
HOST_FLAGS := -std=c11 $(OPTFLAGS) $(DBGFLAGS) -Wall -Wextra -Wpedantic \
-DHOST_PRINTF=1 -Isrc/tasks
HOST_HEAP4_FLAGS := $(HOST_FLAGS) -DHEAP4_HOST_ADAPTER=1 -Iinclude/host-shim
.PHONY: all tasks host \
task1 task2 task3 task4 task5 task6 task7 task8 task9 task10 \
t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 \
host-task1 host-task2 host-task3 host-task4 host-task5 host-task6 host-task7 host-task8 host-task9 host-task10 \
ht1 ht2 ht3 ht4 ht5 ht6 ht7 ht8 ht9 ht10 \
clean check-support $(TASKS)
.PHONY: all tasks host task1 task2 task3 t1 t2 t3 \
host-task1 host-task2 host-task3 ht1 ht2 ht3 clean check-support check-kernel \
$(TASKS)
all: tasks
tasks: $(TASKS)
@@ -59,54 +65,66 @@ host: $(addprefix $(HOST_BUILD_ROOT)/,$(addsuffix /prog,$(TASKS)))
task1 t1: $(word 1,$(TASKS))
task2 t2: $(word 2,$(TASKS))
task3 t3: $(word 3,$(TASKS))
task4 t4: $(word 4,$(TASKS))
task5 t5: $(word 5,$(TASKS))
task6 t6: $(word 6,$(TASKS))
task7 t7: $(word 7,$(TASKS))
task8 t8: $(word 8,$(TASKS))
task9 t9: $(word 9,$(TASKS))
task10 t10: $(word 10,$(TASKS))
host-task1 ht1: $(HOST_BUILD_ROOT)/$(word 1,$(TASKS))/prog
host-task2 ht2: $(HOST_BUILD_ROOT)/$(word 2,$(TASKS))/prog
host-task3 ht3: $(HOST_BUILD_ROOT)/$(word 3,$(TASKS))/prog
host-task4 ht4: $(HOST_BUILD_ROOT)/$(word 4,$(TASKS))/prog
host-task5 ht5: $(HOST_BUILD_ROOT)/$(word 5,$(TASKS))/prog
host-task6 ht6: $(HOST_BUILD_ROOT)/$(word 6,$(TASKS))/prog
host-task7 ht7: $(HOST_BUILD_ROOT)/$(word 7,$(TASKS))/prog
host-task8 ht8: $(HOST_BUILD_ROOT)/$(word 8,$(TASKS))/prog
host-task9 ht9: $(HOST_BUILD_ROOT)/$(word 9,$(TASKS))/prog
host-task10 ht10: $(HOST_BUILD_ROOT)/$(word 10,$(TASKS))/prog
check-support:
@test -f "$(H3_INIT)" || { echo "Missing $(H3_INIT). Run inside rv-env or set RV_ENV_ROOT=/path/to/rv32i-hazard3-env" >&2; exit 1; }
@test -f "$(H3_INIT)" || { echo "Missing $(H3_INIT). Run inside hazard3-sim." >&2; exit 1; }
@test -f "$(LDSCRIPT)" || { echo "Missing $(LDSCRIPT)." >&2; exit 1; }
@test -f "$(MEMOPS)" || { echo "Missing $(MEMOPS)." >&2; exit 1; }
define task_rules
$(1): $(BUILD_ROOT)/$(1)/prog.bin $(BUILD_ROOT)/$(1)/prog.elf $(BUILD_ROOT)/$(1)/prog.lst $(BUILD_ROOT)/$(1)/$(1).s
check-kernel:
@test -f "$(HEAP4_SOURCE)" || { echo "Missing pinned FreeRTOS heap_4.c at $(HEAP4_SOURCE)." >&2; exit 1; }
@grep -F 'FreeRTOS Kernel V11.3.0' "$(FREERTOS_KERNEL_PATH)/include/FreeRTOS.h" >/dev/null || { echo "Expected FreeRTOS Kernel V11.3.0." >&2; exit 1; }
$(BUILD_ROOT)/$(1)/prog.elf: crt0.S src/tasks/$(1).c src/tasks/heap4_common.h $(H3_INIT) $(LDSCRIPT) $(MEMOPS) | check-support
define model_task_rules
$(1): $(BUILD_ROOT)/$(1)/prog.bin $(BUILD_ROOT)/$(1)/prog.elf $(BUILD_ROOT)/$(1)/prog.lst
$(BUILD_ROOT)/$(1)/prog.elf: crt0.S src/tasks/$(1).c src/tasks/heap4_model.h $(H3_INIT) $(LDSCRIPT) $(MEMOPS) | check-support
mkdir -p $$(@D)
$(CC) $(CFLAGS_STEP) $(LINK_FLAGS) -Wl,-Map,$(BUILD_ROOT)/$(1)/prog.map -o $$@ $(H3_INIT) crt0.S $(MEMOPS) src/tasks/$(1).c $(LIBS)
$(CC) $(COMMON_FLAGS) $(MODEL_CPPFLAGS) $(LINK_FLAGS) -Wl,-Map,$(BUILD_ROOT)/$(1)/prog.map -o $$@ $(H3_INIT) crt0.S $(MEMOPS) src/tasks/$(1).c $(LIBS)
$(SIZE) -A -x $$@
$(BUILD_ROOT)/$(1)/prog.bin: $(BUILD_ROOT)/$(1)/prog.elf
$(OBJCOPY) -O binary $$< $$@
$(BUILD_ROOT)/$(1)/prog.lst: $(BUILD_ROOT)/$(1)/prog.elf
$(OBJDUMP) -d -M no-aliases,numeric $$< > $$@
$(OBJDUMP) -d -S -M no-aliases,numeric $$< > $$@
$(BUILD_ROOT)/$(1)/$(1).s: src/tasks/$(1).c src/tasks/heap4_common.h | check-support
$(HOST_BUILD_ROOT)/$(1)/prog: src/tasks/$(1).c src/tasks/heap4_model.h
mkdir -p $$(@D)
$(CC) $(EMIT_FLAGS) -S -o $$@ $$<
$(HOST_BUILD_ROOT)/$(1)/prog: src/tasks/$(1).c src/tasks/heap4_common.h
mkdir -p $$(@D)
$(HOST_CC) $(HOST_CFLAGS) -o $$@ $$<
$(HOST_CC) $(HOST_FLAGS) -o $$@ $$<
endef
$(foreach task,$(TASKS),$(eval $(call task_rules,$(task))))
$(eval $(call model_task_rules,$(word 1,$(TASKS))))
$(eval $(call model_task_rules,$(word 2,$(TASKS))))
TASK03 := $(word 3,$(TASKS))
TASK03_KERNEL_SOURCES := \
$(FREERTOS_KERNEL_PATH)/tasks.c \
$(FREERTOS_KERNEL_PATH)/list.c \
$(HEAP4_SOURCE) \
$(FREERTOS_PORT)/port.c \
$(FREERTOS_PORT)/portASM.S
$(TASK03): $(BUILD_ROOT)/$(TASK03)/prog.bin $(BUILD_ROOT)/$(TASK03)/prog.elf $(BUILD_ROOT)/$(TASK03)/prog.lst
$(BUILD_ROOT)/$(TASK03)/prog.elf: crt0.S src/tasks/$(TASK03).c include/FreeRTOSConfig.h $(TASK03_KERNEL_SOURCES) $(H3_INIT) $(LDSCRIPT) $(MEMOPS) | check-support check-kernel
mkdir -p $(@D)
$(CC) $(COMMON_FLAGS) $(KERNEL_CPPFLAGS) $(LINK_FLAGS) -Wl,-Map,$(BUILD_ROOT)/$(TASK03)/prog.map -o $@ $(H3_INIT) crt0.S $(MEMOPS) $(TASK03_KERNEL_SOURCES) src/tasks/$(TASK03).c $(LIBS)
$(SIZE) -A -x $@
$(BUILD_ROOT)/$(TASK03)/prog.bin: $(BUILD_ROOT)/$(TASK03)/prog.elf
$(OBJCOPY) -O binary $< $@
$(BUILD_ROOT)/$(TASK03)/prog.lst: $(BUILD_ROOT)/$(TASK03)/prog.elf
$(OBJDUMP) -d -S -M no-aliases,numeric $< > $@
$(HOST_BUILD_ROOT)/$(TASK03)/prog: src/tasks/$(TASK03).c include/host-shim/FreeRTOS.h include/host-shim/task.h $(HEAP4_SOURCE) | check-kernel
mkdir -p $(@D)
$(HOST_CC) $(HOST_HEAP4_FLAGS) -o $@ src/tasks/$(TASK03).c $(HEAP4_SOURCE)
clean:
rm -rf $(BUILD_ROOT) $(HOST_BUILD_ROOT)
+115 -30
View File
@@ -1,45 +1,130 @@
# rv32i-freertos / heap4
# Karta pracy: FreeRTOS `heap_4`
Karta pracy 1/? z serii `rv32i-freertos`.
Trzy programy wspierające kartę po K&R 5.4 oraz `structures`:
Temat: mechanika alokatora `heap_4.c` z FreeRTOS-a na małych przykładach
uruchamianych w środowisku RV32I.
1. nagłówek, wyrównanie i geometria splitu na arenie 256 B;
2. lista adresowa + scalanie `A | B | C`;
3. niezmodyfikowany FreeRTOS-Kernel V11.3.0 `heap_4.c`.
Ta karta jest pomostem po kartach C: używa wskaźników, struktur, listy
jednokierunkowej, `static`, `typedef`, makr i arytmetyki adresów, ale nie
wymaga jeszcze schedulera, tasków ani przerwań.
W lekcji 30-minutowej programy 12 są demonstracjami z predykcją. Uczeń
debugguje wyłącznie program 3.
Kod w `src/tasks` jest dydaktycznym modelem zachowania `heap_4`, a nie kopią
pliku upstream FreeRTOS.
Task 3 linkuje upstream `portable/MemMang/heap_4.c` z commita
`9b777ae5c5b8e9e456065a00294d1e5f5f9facf5`.
## Taski
- AMD64: rzeczywisty algorytm + jednowątkowy adapter sekcji krytycznej.
- Hazard3: `tasks.c`, `list.c`, `heap_4.c` i oficjalny port RISC-V.
- RP2350: zgodny core+port z forka Raspberry Pi (`4f7299d6ea74`) oraz
podstawiony stabilny allocator V11.3.0.
- `task01_heap_map.c` - mapa pojęć: sterta, blok, nagłówek bloku.
- `task02_free_list.c` - lista wolnych bloków.
- `task03_heap_init.c` - inicjalizacja sterty i wartownik końca listy.
- `task04_alignment.c` - wyrównanie rozmiarów i adresów.
- `task05_malloc_first_fit.c` - pierwszy pasujący wolny blok.
- `task06_split_block.c` - podział większego bloku.
- `task07_free_insert.c` - zwracanie bloku na listę wolnych.
- `task08_coalescing.c` - scalanie sąsiednich wolnych bloków.
- `task09_config_macros.c` - makra konfiguracyjne i warunkowy `printf`.
- `task10_heap4_demo.c` - mini-demonstracja `malloc/free` bez pełnego RTOS-a.
## Bezpośrednia kontynuacja K&R 5.4
Hostowe `printf` jest dostępne tylko przez `-DHOST_PRINTF=1`; RV32I zapisuje
wyniki w globalnych zmiennych `volatile`.
Lekcja zaczyna się od gotowego projektu z poprzedniej karty:
`allocbuf[64]`, `allocp`, `alloc(5)`, `alloc(7)` oraz offsety
`0 -> 5 -> 12`. Ten alokator:
## Budowanie
- nie potrafi zwolnić pierwszego bloku i zachować drugiego;
- nie przechowuje rozmiaru ani stanu zwróconego obszaru;
- nie zapamiętuje i nie wykorzystuje dziur;
- odzyskuje pamięć wyłącznie przez reset całej areny.
FC01 odpowiada na jedno pytanie projektowe: **co trzeba dodać, aby zwalniać
dowolny blok i ponownie wykorzystywać powstałe miejsce?** Odpowiedzią jest
mechanika `heap_4`: nagłówek bloku, lista wolnych bloków uporządkowana po
adresie, first-fit, split oraz scalanie fizycznych sąsiadów.
FreeRTOS udostępnia kilka wymiennych implementacji tego samego API i projekt
linkuje dokładnie jedną. `heap_1`, `heap_2`, `heap_3` i `heap_5` są w tej
karcie tylko jednominutową mapą kontekstu. Cała obserwowana implementacja to
niezmodyfikowany [`heap_4.c` z FreeRTOS-Kernel V11.3.0](https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V11.3.0/portable/MemMang/heap_4.c).
Lekcja trwa 30 minut. Task 1 i Task 2 są krótkimi demonstracjami z predykcją;
Task 3 jest jedynym centralnym przebiegiem ucznia w debuggerze. Obraz dla
Pico 2 W musi być zbudowany i wgrany przed zajęciami. `heap_4` jest wyborem
linkera projektu, nie sprzętowym mechanizmem RP2350.
## Jedno wejście: `stemctl`
Centralny przebieg lekcji, przygotowany przed wejściem uczniów:
```bash
RV_ENV_ROOT=~/dev/workspace/rv/tools/rv32i-hazard3-student-env make tasks
make host
stemctl debug rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
```
## Praca przez rvctl
Pełna weryfikacja repozytorium wykonywana poza 30-minutową lekcją:
```bash
./rvctl series cards fetch inf heap4
./rvctl card use inf heap4
./rvctl tasks list
./rvctl debug rv32i 1
stemctl series cards fetch freertos heap4
stemctl test native-amd64 freertos heap4 1
stemctl test hazard3-sim freertos heap4 2
stemctl debug hazard3-sim freertos heap4 3
stemctl test rp2350 freertos heap4 3
stemctl deploy rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
stemctl debug rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
```
- `debug rp2350`: roboczy ELF `no_flash` ładowany do SRAM.
- `deploy rp2350`: trwały obraz w SPI flash, odczytany przez breakpointy.
## Kontrakt zadań
| Task | Sprawdza | Wynik kluczowy |
|---|---|---|
| 1 | alignment, header, split | `wanted + remainder == 256` |
| 2 | lista po adresie, coalescing | `2 bloki -> 1 blok`, `96 -> 144 B` |
| 3 | prawdziwe API FreeRTOS | free wraca do F0, minimum nie rośnie, OOM = NULL |
## Debugowanie Task 3
Automatyczny start: `heap4_reset_checkpoint`. Karta prowadzi po ośmiu
powtarzalnych stanach jednego procesu:
| Event | Symbol | Najważniejszy dowód Hazard3 |
|---|---|---|
| E01 | `heap4_reset_checkpoint` | `free=largest=4080`, 1 blok |
| E02 | `heap4_alloc_a_checkpoint` | A(24), `consumed=48`, `free=4032` |
| E03 | `heap4_alloc_b_checkpoint` | B(40), `consumed=64`, `free=3968` |
| E04 | `heap4_alloc_c_checkpoint` | C(16), `consumed=32`, `free=3936` |
| E05 | `heap4_free_a_checkpoint` | `free=3984`, 2 bloki |
| E06 | `heap4_fragmented_checkpoint` | `free=4016`, 2 bloki, `free>largest` |
| E07 | `heap4_coalesced_checkpoint` | `free=largest=4080`, 1 blok |
| E08 | `task03_debug_checkpoint` | OOM `NULL`, hook=1, asserts=0, PASS=1 |
`BlockLink_t` ma na RV32 8 B, ale port wymaga wyrównania 16 B, dlatego
`xHeapStructSize` wynosi 16 B. To rozróżnienie tłumaczy zużycie 48/64/32 B.
```gdb
p g_fragmented_stats
p g_final_stats
p g_a_consumed
p g_b_consumed
p g_c_consumed
p xFreeBytesRemaining
p xMinimumEverFreeBytesRemaining
p xStart
p pxEnd
x/160bx ucHeap
b prvInsertBlockIntoFreeList
b pvPortMalloc
b vPortFree
```
Scalanie sprawdzamy z replay E06: zatrzymujemy się przed `vPortFree(g_b)`,
ustawiamy tymczasowy breakpoint na `prvInsertBlockIntoFreeList` i krokujemy.
Upstream V11.3.0 scala najpierw poprzedni/lewy, a potem następny/prawy blok.
Pełna macierz kroków diagramów jest w
[`doc/hazard3-iteration-plan.md`](doc/hazard3-iteration-plan.md).
W UI: Termdebug po lewej; źródło i listing po prawej; bash pod Neovimem.
`F5` continue, `F9` breakpoint, `F10` next, `F11` step, `Shift-F11`
finish, `F8` stepi, `:StudentStack`, `:StudentMemory`, `:StudentLst`.
## Test repozytorium
```bash
./tests/test_host.sh
bash -n tools/card-action.sh
./scripts/render_pdf.sh
```
Źródło i licencja: [UPSTREAM.md](UPSTREAM.md).
+19
View File
@@ -0,0 +1,19 @@
# Upstream contract
- Project: FreeRTOS-Kernel
- Version: V11.3.0
- Commit: `9b777ae5c5b8e9e456065a00294d1e5f5f9facf5`
- Source used by Task 3: `portable/MemMang/heap_4.c`
- License: MIT (as shipped in the pinned upstream checkout)
RP2350 needs a port that is newer than the V11.3.0 tag:
- Project: Raspberry Pi fork of FreeRTOS-Kernel
- Commit: `4f7299d6ea746b27a9dd19e87af568e34bd65b15`
- Files used on RP2350: matching kernel core plus
`portable/ThirdParty/GCC/RP2350_RISC-V`
- Allocator used on RP2350: still the stable V11.3.0 `heap_4.c` above,
compiled instead of the fork's development-branch allocator.
The canonical containers provide `/opt/FreeRTOS-Kernel`; the RP2350 profile
also provides `/opt/FreeRTOS-RP2350`. The card carries no allocator copy.
-53
View File
@@ -1,53 +0,0 @@
.file "task01_heap_map.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
li a5,8
sw a5,g_header_size,a4
sw a5,g_aligned_header_size,a4
li a5,1
sw a5,g_allocated_bit_set,a4
lla a5,g_total_block_bytes
li a4,24
sw a4,0(a5)
lw a5,0(a5)
addi a5,a5,-8
sw a5,g_user_bytes,a4
li a0,0
ret
.size main, .-main
.globl g_total_block_bytes
.globl g_user_bytes
.globl g_allocated_bit_set
.globl g_aligned_header_size
.globl g_header_size
.section .sbss,"aw",@nobits
.align 2
.type g_total_block_bytes, @object
.size g_total_block_bytes, 4
g_total_block_bytes:
.zero 4
.type g_user_bytes, @object
.size g_user_bytes, 4
g_user_bytes:
.zero 4
.type g_allocated_bit_set, @object
.size g_allocated_bit_set, 4
g_allocated_bit_set:
.zero 4
.type g_aligned_header_size, @object
.size g_aligned_header_size, 4
g_aligned_header_size:
.zero 4
.type g_header_size, @object
.size g_header_size, 4
g_header_size:
.zero 4
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
-73
View File
@@ -1,73 +0,0 @@
.file "task02_free_list.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
addi sp,sp,-32
addi a5,sp,16
sw a5,24(sp)
li a5,32
sw a5,28(sp)
addi a5,sp,8
sw a5,16(sp)
li a5,80
sw a5,20(sp)
sw zero,8(sp)
li a5,24
sw a5,12(sp)
li a4,0
add a5,sp,a5
.L2:
lw a3,4(a5)
add a4,a4,a3
lw a5,0(a5)
bne a5,zero,.L2
sw a4,g_free_total,a5
li a3,0
addi a5,sp,24
j .L4
.L3:
lw a5,0(a5)
beq a5,zero,.L10
.L4:
lw a4,4(a5)
bgeu a3,a4,.L3
mv a3,a4
j .L3
.L10:
sw a3,g_largest_free,a5
addi a5,sp,24
li a4,0
.L5:
addi a4,a4,1
lw a5,0(a5)
bne a5,zero,.L5
sw a4,g_node_count,a5
li a0,0
addi sp,sp,32
jr ra
.size main, .-main
.globl g_node_count
.globl g_largest_free
.globl g_free_total
.section .sbss,"aw",@nobits
.align 2
.type g_node_count, @object
.size g_node_count, 4
g_node_count:
.zero 4
.type g_largest_free, @object
.size g_largest_free, 4
g_largest_free:
.zero 4
.type g_free_total, @object
.size g_free_total, 4
g_free_total:
.zero 4
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
-74
View File
@@ -1,74 +0,0 @@
.file "task03_heap_init.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
lla a2,.LANCHOR0
andi a4,a2,7
mv a5,a2
beq a4,zero,.L2
andi a5,a2,-8
addi a5,a5,8
.L2:
lla a3,.LANCHOR0+160
sub a3,a3,a5
addi a4,a5,-8
andi a3,a3,-8
add a4,a4,a3
sw a4,end_marker,a3
sw zero,0(a4)
sw zero,4(a4)
sw a4,0(a5)
sub a3,a4,a5
sw a3,4(a5)
lla a1,start
sw a5,0(a1)
sw zero,4(a1)
sub a5,a5,a2
sw a5,g_aligned_offset,a2
sw a3,g_initial_free_size,a5
lw a5,0(a4)
seqz a5,a5
sw a5,g_end_is_last,a4
li a0,0
ret
.size main, .-main
.globl g_end_is_last
.globl g_aligned_offset
.globl g_initial_free_size
.bss
.align 2
.set .LANCHOR0,. + 0
.type heap_area, @object
.size heap_area, 168
heap_area:
.zero 168
.section .sbss,"aw",@nobits
.align 2
.type g_end_is_last, @object
.size g_end_is_last, 4
g_end_is_last:
.zero 4
.type g_aligned_offset, @object
.size g_aligned_offset, 4
g_aligned_offset:
.zero 4
.type g_initial_free_size, @object
.size g_initial_free_size, 4
g_initial_free_size:
.zero 4
.type end_marker, @object
.size end_marker, 4
end_marker:
.zero 4
.type start, @object
.size start, 8
start:
.zero 8
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
-47
View File
@@ -1,47 +0,0 @@
.file "task04_alignment.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
addi sp,sp,-32
li a5,16
sw a5,g_request_1,a4
li a5,24
sw a5,g_request_9,a4
li a5,32
sw a5,g_request_17,a4
li a5,7
sw a5,g_address_delta,a4
li a0,0
addi sp,sp,32
jr ra
.size main, .-main
.globl g_address_delta
.globl g_request_17
.globl g_request_9
.globl g_request_1
.section .sbss,"aw",@nobits
.align 2
.type g_address_delta, @object
.size g_address_delta, 4
g_address_delta:
.zero 4
.type g_request_17, @object
.size g_request_17, 4
g_request_17:
.zero 4
.type g_request_9, @object
.size g_request_9, 4
g_request_9:
.zero 4
.type g_request_1, @object
.size g_request_1, 4
g_request_1:
.zero 4
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
@@ -1,95 +0,0 @@
.file "task05_malloc_first_fit.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
lla a4,.LANCHOR0
andi a5,a4,7
beq a5,zero,.L2
andi a4,a4,-8
addi a4,a4,8
.L2:
mv a5,a4
addi a3,a4,120
sw a3,end_marker,a2
sw zero,120(a4)
sw zero,4(a3)
sw a3,0(a4)
li a2,120
sw a2,4(a4)
lla a2,start
sw a4,0(a2)
sw zero,4(a2)
li a1,31
j .L5
.L6:
mv a5,a4
.L5:
lw a4,4(a5)
bgtu a4,a1,.L7
lw a4,0(a5)
mv a2,a5
bne a4,a3,.L6
li a5,0
j .L4
.L7:
lw a4,0(a5)
sw a4,0(a2)
sw zero,0(a5)
lw a4,4(a5)
li a3,-2147483648
or a4,a4,a3
sw a4,4(a5)
addi a5,a5,8
.L4:
snez a4,a5
sw a4,g_allocation_ok,a3
lw a5,-4(a5)
slli a5,a5,1
srli a5,a5,1
sw a5,g_allocated_size,a4
lw a5,start
lw a5,4(a5)
sw a5,g_remaining_free,a4
li a0,0
ret
.size main, .-main
.globl g_allocation_ok
.globl g_remaining_free
.globl g_allocated_size
.bss
.align 2
.set .LANCHOR0,. + 0
.type heap_area, @object
.size heap_area, 136
heap_area:
.zero 136
.section .sbss,"aw",@nobits
.align 2
.type g_allocation_ok, @object
.size g_allocation_ok, 4
g_allocation_ok:
.zero 4
.type g_remaining_free, @object
.size g_remaining_free, 4
g_remaining_free:
.zero 4
.type g_allocated_size, @object
.size g_allocated_size, 4
g_allocated_size:
.zero 4
.type end_marker, @object
.size end_marker, 4
end_marker:
.zero 4
.type start, @object
.size start, 8
start:
.zero 8
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
@@ -1,117 +0,0 @@
.file "task06_split_block.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
lla a4,.LANCHOR0
andi a5,a4,7
beq a5,zero,.L2
andi a4,a4,-8
addi a4,a4,8
.L2:
mv a5,a4
addi a3,a4,176
sw a3,end_marker,a2
sw zero,176(a4)
sw zero,4(a3)
sw a3,0(a4)
li a2,176
sw a2,4(a4)
lla a2,start
sw a4,0(a2)
sw zero,4(a2)
li a1,39
j .L7
.L10:
mv a5,a4
.L7:
lw a4,4(a5)
bgtu a4,a1,.L13
lw a4,0(a5)
mv a2,a5
bne a4,a3,.L10
li a5,0
j .L6
.L13:
addi a4,a4,-40
li a1,16
bleu a4,a1,.L4
sw a4,44(a5)
lw a4,0(a5)
sw a4,40(a5)
addi a4,a5,40
sw a4,0(a2)
li a4,40
sw a4,4(a5)
.L5:
sw zero,0(a5)
lw a4,4(a5)
li a2,-2147483648
or a4,a4,a2
sw a4,4(a5)
addi a5,a5,8
.L6:
lw a5,-4(a5)
slli a5,a5,1
srli a5,a5,1
sw a5,g_allocated_size,a4
lw a5,start
lw a4,4(a5)
sw a4,g_split_free_size,a2
beq a5,a3,.L11
li a4,0
.L9:
addi a4,a4,1
lw a5,0(a5)
bne a5,a3,.L9
.L8:
sw a4,g_free_nodes,a5
li a0,0
ret
.L4:
lw a4,0(a5)
sw a4,0(a2)
j .L5
.L11:
li a4,0
j .L8
.size main, .-main
.globl g_free_nodes
.globl g_split_free_size
.globl g_allocated_size
.bss
.align 2
.set .LANCHOR0,. + 0
.type heap_area, @object
.size heap_area, 200
heap_area:
.zero 200
.section .sbss,"aw",@nobits
.align 2
.type g_free_nodes, @object
.size g_free_nodes, 4
g_free_nodes:
.zero 4
.type g_split_free_size, @object
.size g_split_free_size, 4
g_split_free_size:
.zero 4
.type g_allocated_size, @object
.size g_allocated_size, 4
g_allocated_size:
.zero 4
.type end_marker, @object
.size end_marker, 4
end_marker:
.zero 4
.type start, @object
.size start, 8
start:
.zero 8
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
@@ -1,116 +0,0 @@
.file "task07_free_insert.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
lla a5,.LANCHOR0
lla a4,.LANCHOR0+176
sw a4,end_marker,a3
sw a5,start,a3
lla a3,.LANCHOR0+128
sw a3,0(a5)
sw a4,128(a5)
sw zero,176(a5)
li a4,40
sw a4,4(a5)
li a4,48
sw a4,132(a5)
sw zero,180(a5)
li a4,32
sw a4,68(a5)
lla a5,start
lla a3,.LANCHOR0+64
.L2:
mv a4,a5
lw a5,0(a5)
bltu a5,a3,.L2
lla a3,.LANCHOR0
sw a5,64(a3)
lla a5,.LANCHOR0+64
sw a5,0(a4)
lw a5,start
beq a5,a3,.L16
sw zero,g_order_ok,a4
lla a4,.LANCHOR0+176
beq a5,a4,.L5
.L9:
mv a4,a5
li a3,0
lla a2,.LANCHOR0+176
.L6:
addi a3,a3,1
lw a4,0(a4)
bne a4,a2,.L6
sw a3,g_free_count,a4
li a4,0
lla a2,.LANCHOR0+176
.L7:
lw a3,4(a5)
add a4,a4,a3
lw a5,0(a5)
bne a5,a2,.L7
.L8:
sw a4,g_total_free,a5
li a0,0
ret
.L16:
lla a3,.LANCHOR0+64
lw a2,.LANCHOR0
li a4,0
beq a2,a3,.L17
.L4:
sw a4,g_order_ok,a3
j .L9
.L17:
lla a3,.LANCHOR0+128
lw a2,.LANCHOR0+64
bne a2,a3,.L4
lla a3,.LANCHOR0+176
lw a4,.LANCHOR0+128
sub a4,a4,a3
seqz a4,a4
j .L4
.L5:
sw zero,g_free_count,a5
li a4,0
j .L8
.size main, .-main
.globl g_total_free
.globl g_free_count
.globl g_order_ok
.bss
.align 2
.set .LANCHOR0,. + 0
.type heap_area, @object
.size heap_area, 192
heap_area:
.zero 192
.section .sbss,"aw",@nobits
.align 2
.type g_total_free, @object
.size g_total_free, 4
g_total_free:
.zero 4
.type g_free_count, @object
.size g_free_count, 4
g_free_count:
.zero 4
.type g_order_ok, @object
.size g_order_ok, 4
g_order_ok:
.zero 4
.type end_marker, @object
.size end_marker, 4
end_marker:
.zero 4
.type start, @object
.size start, 8
start:
.zero 8
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
-116
View File
@@ -1,116 +0,0 @@
.file "task08_coalescing.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
lla a5,.LANCHOR0
lla a4,.LANCHOR0+160
sw a4,end_marker,a3
sw a5,start,a3
lla a3,.LANCHOR0+96
sw a3,0(a5)
sw a4,96(a5)
sw zero,160(a5)
li a4,48
sw a4,4(a5)
sw a4,52(a5)
li a4,64
sw a4,100(a5)
sw zero,164(a5)
lla a5,start
lla a3,.LANCHOR0+48
.L2:
mv a4,a5
lw a5,0(a5)
bltu a5,a3,.L2
lla a3,.LANCHOR0+96
beq a5,a3,.L12
.L3:
sw a5,.LANCHOR0+48,a3
lla a5,start
lla a3,.LANCHOR0+48
beq a4,a5,.L4
lw a2,4(a4)
slli a5,a2,1
srli a5,a5,1
add a5,a4,a5
beq a5,a3,.L13
.L4:
sw a3,0(a4)
lw a2,start
lla a5,.LANCHOR0+160
beq a2,a5,.L9
mv a5,a2
li a4,0
lla a3,.LANCHOR0+160
.L6:
addi a4,a4,1
lw a5,0(a5)
bne a5,a3,.L6
.L5:
sw a4,g_free_count,a5
lw a5,4(a2)
sw a5,g_merged_size,a4
lw a5,0(a2)
lla a4,.LANCHOR0+160
sub a5,a5,a4
seqz a5,a5
sw a5,g_merged_with_right,a4
li a0,0
ret
.L12:
li a5,112
sw a5,.LANCHOR0+52,a3
lw a5,0(a4)
lw a5,0(a5)
j .L3
.L13:
lla a3,.LANCHOR0
lw a5,52(a3)
add a5,a5,a2
sw a5,4(a4)
lw a3,48(a3)
j .L4
.L9:
li a4,0
j .L5
.size main, .-main
.globl g_merged_with_right
.globl g_merged_size
.globl g_free_count
.bss
.align 2
.set .LANCHOR0,. + 0
.type heap_area, @object
.size heap_area, 192
heap_area:
.zero 192
.section .sbss,"aw",@nobits
.align 2
.type g_merged_with_right, @object
.size g_merged_with_right, 4
g_merged_with_right:
.zero 4
.type g_merged_size, @object
.size g_merged_size, 4
g_merged_size:
.zero 4
.type g_free_count, @object
.size g_free_count, 4
g_free_count:
.zero 4
.type end_marker, @object
.size end_marker, 4
end_marker:
.zero 4
.type start, @object
.size start, 8
start:
.zero 8
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
@@ -1,44 +0,0 @@
.file "task09_config_macros.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.globl main
.type main, @function
main:
li a5,256
sw a5,g_total_heap,a4
li a5,248
sw a5,g_adjusted_heap,a4
li a5,1
sw a5,g_dynamic_enabled,a4
sw zero,g_trace_is_host_only,a5
li a0,0
ret
.size main, .-main
.globl g_trace_is_host_only
.globl g_dynamic_enabled
.globl g_adjusted_heap
.globl g_total_heap
.section .sbss,"aw",@nobits
.align 2
.type g_trace_is_host_only, @object
.size g_trace_is_host_only, 4
g_trace_is_host_only:
.zero 4
.type g_dynamic_enabled, @object
.size g_dynamic_enabled, 4
g_dynamic_enabled:
.zero 4
.type g_adjusted_heap, @object
.size g_adjusted_heap, 4
g_adjusted_heap:
.zero 4
.type g_total_heap, @object
.size g_total_heap, 4
g_total_heap:
.zero 4
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
-253
View File
@@ -1,253 +0,0 @@
.file "task10_heap4_demo.c"
.option nopic
.attribute arch, "rv32i2p1_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 2
.type heap_malloc_model, @function
heap_malloc_model:
beq a0,zero,.L1
addi a4,a0,8
andi a0,a0,7
beq a0,zero,.L3
andi a4,a4,-8
addi a4,a4,8
.L3:
lw a0,start
lw a3,end_marker
beq a0,a3,.L10
lla a2,start
j .L8
.L11:
mv a0,a5
.L8:
lw a5,4(a0)
bgeu a5,a4,.L12
lw a5,0(a0)
mv a2,a0
bne a5,a3,.L11
li a0,0
ret
.L12:
sub a3,a5,a4
li a1,16
bleu a3,a1,.L5
add a5,a0,a4
sw a3,4(a5)
lw a3,0(a0)
sw a3,0(a5)
sw a5,0(a2)
sw a4,4(a0)
.L6:
sw zero,0(a0)
lw a5,4(a0)
li a3,-2147483648
or a5,a5,a3
sw a5,4(a0)
lla a3,free_bytes_remaining
lw a5,0(a3)
sub a5,a5,a4
sw a5,0(a3)
lw a4,minimum_ever_free
bgeu a5,a4,.L7
sw a5,minimum_ever_free,a4
.L7:
addi a0,a0,8
ret
.L5:
lw a4,0(a0)
sw a4,0(a2)
mv a4,a5
j .L6
.L10:
li a0,0
.L1:
ret
.size heap_malloc_model, .-heap_malloc_model
.align 2
.type heap_free_model, @function
heap_free_model:
beq a0,zero,.L13
lw a5,-4(a0)
blt a5,zero,.L19
.L13:
ret
.L19:
addi a3,a0,-8
slli a5,a5,1
srli a2,a5,1
sw a2,-4(a0)
lla a4,free_bytes_remaining
lw a5,0(a4)
add a5,a5,a2
sw a5,0(a4)
lla a5,start
.L15:
mv a4,a5
lw a5,0(a5)
bgtu a3,a5,.L15
add a1,a3,a2
beq a5,a1,.L20
.L16:
sw a5,-8(a0)
lla a5,start
beq a4,a5,.L17
lw a2,4(a4)
slli a5,a2,1
srli a5,a5,1
add a5,a4,a5
beq a3,a5,.L21
.L17:
sw a3,0(a4)
ret
.L20:
lw a5,4(a5)
add a5,a5,a2
sw a5,-4(a0)
lw a5,0(a4)
lw a5,0(a5)
j .L16
.L21:
lw a5,-4(a0)
add a5,a5,a2
sw a5,4(a4)
lw a5,-8(a0)
sw a5,0(a4)
ret
.size heap_free_model, .-heap_free_model
.align 2
.globl main
.type main, @function
main:
addi sp,sp,-32
sw ra,28(sp)
sw s0,24(sp)
sw s1,20(sp)
sw s2,16(sp)
sw s3,12(sp)
sw s4,8(sp)
lla a4,.LANCHOR0
andi a3,a4,7
mv a5,a4
beq a3,zero,.L23
andi a4,a4,-8
addi a5,a4,8
.L23:
lla s0,.LANCHOR0+256
sub s0,s0,a5
andi s0,s0,-8
addi a4,a5,-8
add s0,s0,a4
sw s0,end_marker,a4
sw zero,0(s0)
sw zero,4(s0)
sw s0,0(a5)
sub a4,s0,a5
sw a4,4(a5)
lla s4,start
sw a5,0(s4)
sw zero,4(s4)
sw a4,free_bytes_remaining,a5
sw a4,minimum_ever_free,a5
li a0,24
call heap_malloc_model
mv s2,a0
li a0,40
call heap_malloc_model
mv s3,a0
mv a0,s2
call heap_free_model
li a0,16
call heap_malloc_model
mv s1,a0
mv a0,s3
call heap_free_model
mv a0,s1
call heap_free_model
snez s2,s2
snez s3,s3
and s2,s2,s3
snez s1,s1
and s1,s1,s2
sw s1,g_allocations_ok,a5
lw a5,0(s4)
beq s0,a5,.L24
mv a4,a5
li a3,0
.L25:
addi a3,a3,1
lw a4,0(a4)
bne s0,a4,.L25
sw a3,g_final_free_nodes,a2
li a3,0
.L26:
lw a2,4(a5)
add a3,a3,a2
lw a5,0(a5)
bne a5,a4,.L26
.L27:
sw a3,g_final_free_total,a5
lw a5,minimum_ever_free
sw a5,g_minimum_ever_free,a4
li a0,0
lw ra,28(sp)
lw s0,24(sp)
lw s1,20(sp)
lw s2,16(sp)
lw s3,12(sp)
lw s4,8(sp)
addi sp,sp,32
jr ra
.L24:
sw zero,g_final_free_nodes,a5
li a3,0
j .L27
.size main, .-main
.globl g_minimum_ever_free
.globl g_final_free_total
.globl g_final_free_nodes
.globl g_allocations_ok
.bss
.align 2
.set .LANCHOR0,. + 0
.type heap_area, @object
.size heap_area, 264
heap_area:
.zero 264
.section .sbss,"aw",@nobits
.align 2
.type minimum_ever_free, @object
.size minimum_ever_free, 4
minimum_ever_free:
.zero 4
.type free_bytes_remaining, @object
.size free_bytes_remaining, 4
free_bytes_remaining:
.zero 4
.type g_minimum_ever_free, @object
.size g_minimum_ever_free, 4
g_minimum_ever_free:
.zero 4
.type g_final_free_total, @object
.size g_final_free_total, 4
g_final_free_total:
.zero 4
.type g_final_free_nodes, @object
.size g_final_free_nodes, 4
g_final_free_nodes:
.zero 4
.type g_allocations_ok, @object
.size g_allocations_ok, 4
g_allocations_ok:
.zero 4
.type end_marker, @object
.size end_marker, 4
end_marker:
.zero 4
.type start, @object
.size start, 8
start:
.zero 8
.ident "GCC: (15.2.0-23) 15.2.0"
.section .note.GNU-stack,"",@progbits
Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

+31
View File
@@ -0,0 +1,31 @@
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A1 CONTEXT — from linear cursor to reusable heap
rectangle "<<application>>\n01 A / B / C experiment\nrequests payload bytes" as APP
rectangle "<<public API>>\n02 pvPortMalloc / vPortFree\nheap statistics" as API
rectangle "<<allocator>>\n03 heap_4\nfirst-fit · split · coalesce" as H4
rectangle "<<arena>>\n04 ucHeap[4096]\nheaders + payload" as ARENA
rectangle "<<target>>\n05 Hazard3 / RV32I\nGDB · registers · memory" as TARGET
APP -down-> API : request / release
API -down-> H4 : direct C call
H4 -down-> ARENA : manages
ARENA -down-> TARGET : stored in RAM
note right of H4
heap_1: allocate only
heap_2: free, no coalesce
heap_3: libc wrapper
heap_4: free + coalesce
heap_5: multiple regions
end note
@enduml
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="600.3488px" preserveAspectRatio="none" style="width:311px;height:600px;" version="1.1" viewBox="0 0 311 600" width="311.19px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="227.6552" x="44.9803" y="9.813">A1 CONTEXT — from linear cursor to reusable heap</text><!--MD5=[cd187d11655e4367e900de538d2f1d0c]
entity APP--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="121.1713" x="15.6054" y="20.2686"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="58.7497" x="24.785" y="39.2613">«application»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="102.812" x="24.785" y="51.764">01 A / B / C experiment</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="102.812" x="24.785" y="64.2667">requests payload bytes</text><!--MD5=[645d8587175d8f7ad110cd370775931d]
entity API--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="141.3665" x="5.5078" y="144.9833"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="52.324" x="14.6874" y="163.976">«public API»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="123.0073" x="14.6874" y="176.4787">02 pvPortMalloc / vPortFree</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="65.1755" x="14.6874" y="188.9813">heap statistics</text><!--MD5=[46e692d45a0b60d87b097c4043ce42a2]
entity H4--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="122.0893" x="15.1464" y="277.6108"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="48.6521" x="24.3261" y="296.6035">«allocator»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="44.9803" x="24.3261" y="309.1062">03 heap_4</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="103.73" x="24.3261" y="321.6088">first-fit · split · coalesce</text><!--MD5=[a55d5013c595d66e4d3c908e0eed28a7]
entity ARENA--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="100.0581" x="26.162" y="410.2384"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="34.8827" x="35.3416" y="429.231">«arena»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="74.3551" x="35.3416" y="441.7337">04 ucHeap[4096]</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="81.6988" x="35.3416" y="454.2364">headers + payload</text><!--MD5=[aba7613092619c8a5fef3de1c87efe89]
entity TARGET--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="129.433" x="11.4746" y="534.953"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="36.7186" x="20.6542" y="553.9457">«target»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="84.4527" x="20.6542" y="566.4484">05 Hazard3 / RV32I</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="111.0737" x="20.6542" y="578.951">GDB · registers · memory</text><path d="M169.3645,269.698 L169.3645,301.8726 L137.6029,305.5445 L169.3645,309.2164 L169.3645,341.391 A0,0 0 0 0 169.3645,341.391 L300.6334,341.391 A0,0 0 0 0 300.6334,341.391 L300.6334,278.8776 L291.4538,269.698 L169.3645,269.698 A0,0 0 0 0 169.3645,269.698 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.9179645841402695;"/><path d="M291.4538,269.698 L291.4538,278.8776 L300.6334,278.8776 L291.4538,269.698 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="93.6324" x="174.8723" y="284.1008">heap_1: allocate only</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="111.9917" x="174.8723" y="296.6035">heap_2: free, no coalesce</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="91.7965" x="174.8723" y="309.1062">heap_3: libc wrapper</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="103.73" x="174.8723" y="321.6088">heap_4: free + coalesce</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="109.2378" x="174.8723" y="334.1115">heap_5: multiple regions</text><!--MD5=[ec942d3abfeef98a0155e2f031d4c131]
link APP to API--><path d="M76.1911,76.393 C76.1911,94.8441 76.1911,119.3262 76.1911,138.8972 " fill="none" id="APP-&gt;API" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,143.4136,79.8629,135.1519,76.1911,138.8238,72.5192,135.1519,76.1911,143.4136" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="76.1911" x="77.109" y="114.4059">request / release</text><!--MD5=[798ded9ffd9ac635cdedeacba358c97c]
link API to H4--><path d="M76.1911,201.2545 C76.1911,221.6609 76.1911,249.6129 76.1911,271.3044 " fill="none" id="API-&gt;H4" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,275.8575,79.8629,267.5958,76.1911,271.2677,72.5192,267.5958,76.1911,275.8575" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="52.324" x="77.109" y="239.1206">direct C call</text><!--MD5=[26d2234bc3ca60bb174d49bba6317b2c]
link H4 to ARENA--><path d="M76.1911,333.8821 C76.1911,354.2884 76.1911,382.2404 76.1911,403.9319 " fill="none" id="H4-&gt;ARENA" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,408.485,79.8629,400.2234,76.1911,403.8952,72.5192,400.2234,76.1911,408.485" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="40.3904" x="77.109" y="379.661">manages</text><!--MD5=[057090cc36f41caea0c560281f72f0d5]
link ARENA to TARGET--><path d="M76.1911,466.3627 C76.1911,484.8138 76.1911,509.2959 76.1911,528.8669 " fill="none" id="ARENA-&gt;TARGET" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,533.3833,79.8629,525.1216,76.1911,528.7935,72.5192,525.1216,76.1911,533.3833" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="61.5036" x="77.109" y="504.3756">stored in RAM</text><!--MD5=[5f927a6771e8d55dac04e3c75dd184e1]
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A1 CONTEXT — from linear cursor to reusable heap
rectangle "<<application>>\n01 A / B / C experiment\nrequests payload bytes" as APP
rectangle "<<public API>>\n02 pvPortMalloc / vPortFree\nheap statistics" as API
rectangle "<<allocator>>\n03 heap_4\nfirst-fit · split · coalesce" as H4
rectangle "<<arena>>\n04 ucHeap[4096]\nheaders + payload" as ARENA
rectangle "<<target>>\n05 Hazard3 / RV32I\nGDB · registers · memory" as TARGET
APP -down-> API : request / release
API -down-> H4 : direct C call
H4 -down-> ARENA : manages
ARENA -down-> TARGET : stored in RAM
note right of H4
heap_1: allocate only
heap_2: free, no coalesce
heap_3: libc wrapper
heap_4: free + coalesce
heap_5: multiple regions
end note
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+53
View File
@@ -0,0 +1,53 @@
@startuml
scale 620 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam classBorderColor #2c7794
skinparam classBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A2 STRUCTURE — RV32 header, split and two-sided coalescing
class "01 Block header" as HEADER {
next : BlockLink_t*
size : size_t
raw sizeof = 8 bytes on RV32
aligned xHeapStructSize = 16
}
class "Allocated block" as ALLOC {
02 A: header + 24 byte request
aligned total = 48 bytes
payload begins after header
}
class "03 Free remainder" as REM {
own header
free = 4032 bytes after A
}
HEADER *-- ALLOC : precedes payload
ALLOC -down-> REM : first-fit + split
class "04 Address-ordered free list" as LIST {
previous < inserted < current
A < B < C+tail
}
class "05 Previous / left neighbour" as LEFT {
previous + previous.size == inserted
merge previous first
}
class "06 Next / right neighbour" as RIGHT {
merged + merged.size == current
merge next second
}
REM -down-> LIST : insert by address
LIST -down-> LEFT : heap_4 tests first
LEFT -down-> RIGHT : then tests next
note right of LIST
Address order exposes both physical
neighbours without scanning the arena.
end note
@enduml
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="620.2694px" preserveAspectRatio="none" style="width:312px;height:620px;" version="1.1" viewBox="0 0 312 620" width="312.6158px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="211.9549" x="52.4571" y="7.5779">A2 STRUCTURE — RV32 header, split and two-sided coalescing</text><!--MD5=[9827fb78ff6e3f59cfadf959dc26af7c]
class HEADER--><rect fill="#EDF6FA" height="69.8104" id="HEADER" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="107.7497" x="16.3042" y="15.1133"/><ellipse cx="40.1935" cy="25.0376" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M41.1017,27.3747 Q40.858,27.4965 40.5922,27.5519 Q40.3264,27.6184 40.0273,27.6184 Q38.9861,27.6184 38.4323,26.9316 Q37.8896,26.2449 37.8896,24.9379 Q37.8896,23.6309 38.4323,22.9442 Q38.9861,22.2575 40.0273,22.2575 Q40.3264,22.2575 40.5922,22.3239 Q40.8691,22.3793 41.1017,22.5011 L41.1017,23.642 Q40.8359,23.3983 40.5811,23.2876 Q40.3374,23.1768 40.0827,23.1768 Q39.5178,23.1768 39.2298,23.6198 Q38.9418,24.0629 38.9418,24.9379 Q38.9418,25.8129 39.2298,26.256 Q39.5178,26.699 40.0827,26.699 Q40.3374,26.699 40.5811,26.5883 Q40.8359,26.4775 41.1017,26.2338 L41.1017,27.3747 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="55.2926" x="51.9609" y="27.7881">01 Block header</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="17.0131" x2="123.345" y1="34.9619" y2="34.9619"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="63.0903" x="20.5575" y="45.3753">next : BlockLink_t*</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="38.9884" x="20.5575" y="55.0303">size : size_t</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="97.8253" x="20.5575" y="64.6852">raw sizeof = 8 bytes on RV32</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="99.2431" x="20.5575" y="74.3401">aligned xHeapStructSize = 16</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="17.0131" x2="123.345" y1="79.2527" y2="79.2527"/><!--MD5=[40d637119be40bcfdc4ce848efbdda9e]
class ALLOC--><rect fill="#EDF6FA" height="60.1555" id="ALLOC" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="114.1296" x="13.1143" y="138.0897"/><ellipse cx="41.6467" cy="148.014" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M42.5549,150.3511 Q42.3112,150.4729 42.0454,150.5283 Q41.7796,150.5948 41.4805,150.5948 Q40.4393,150.5948 39.8855,149.908 Q39.3428,149.2213 39.3428,147.9143 Q39.3428,146.6073 39.8855,145.9206 Q40.4393,145.2339 41.4805,145.2339 Q41.7796,145.2339 42.0454,145.3003 Q42.3223,145.3557 42.5549,145.4775 L42.5549,146.6184 Q42.2891,146.3747 42.0343,146.2639 Q41.7906,146.1532 41.5359,146.1532 Q40.971,146.1532 40.683,146.5962 Q40.395,147.0393 40.395,147.9143 Q40.395,148.7893 40.683,149.2324 Q40.971,149.6754 41.5359,149.6754 Q41.7906,149.6754 42.0343,149.5647 Q42.2891,149.4539 42.5549,149.2102 L42.5549,150.3511 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="51.7482" x="54.052" y="150.7644">Allocated block</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.8231" x2="126.535" y1="157.9383" y2="157.9383"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="105.623" x="17.3675" y="168.3517">02 A: header + 24 byte request</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="81.5211" x="17.3675" y="178.0067">aligned total = 48 bytes</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="96.4076" x="17.3675" y="187.6616">payload begins after header</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.8231" x2="126.535" y1="192.5741" y2="192.5741"/><!--MD5=[71c2adef9be32489055f250a531e7c6f]
class REM--><rect fill="#EDF6FA" height="50.5005" id="REM" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="92.8632" x="23.7475" y="251.4111"/><ellipse cx="37.4288" cy="261.3354" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M38.3371,263.6725 Q38.0934,263.7944 37.8276,263.8497 Q37.5617,263.9162 37.2627,263.9162 Q36.2215,263.9162 35.6677,263.2295 Q35.125,262.5427 35.125,261.2357 Q35.125,259.9287 35.6677,259.242 Q36.2215,258.5553 37.2627,258.5553 Q37.5617,258.5553 37.8276,258.6218 Q38.1045,258.6771 38.3371,258.799 L38.3371,259.9398 Q38.0712,259.6961 37.8165,259.5854 Q37.5728,259.4746 37.3181,259.4746 Q36.7532,259.4746 36.4652,259.9177 Q36.1772,260.3607 36.1772,261.2357 Q36.1772,262.1108 36.4652,262.5538 Q36.7532,262.9969 37.3181,262.9969 Q37.5728,262.9969 37.8165,262.8861 Q38.0712,262.7753 38.3371,262.5317 L38.3371,263.6725 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="63.0903" x="46.9278" y="264.0859">03 Free remainder</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="24.4563" x2="115.9018" y1="271.2597" y2="271.2597"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="40.4061" x="28.0007" y="281.6732">own header</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="84.3566" x="28.0007" y="291.3281">free = 4032 bytes after A</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="24.4563" x2="115.9018" y1="296.2406" y2="296.2406"/><!--MD5=[b0a0edd67d9eafaaa5639bbe6382adce]
class LIST--><rect fill="#EDF6FA" height="50.5005" id="LIST" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="114.8384" x="12.7598" y="355.0776"/><ellipse cx="21.9753" cy="365.0019" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M22.8835,367.339 Q22.6398,367.4609 22.374,367.5162 Q22.1082,367.5827 21.8091,367.5827 Q20.7679,367.5827 20.2141,366.896 Q19.6714,366.2093 19.6714,364.9023 Q19.6714,363.5953 20.2141,362.9085 Q20.7679,362.2218 21.8091,362.2218 Q22.1082,362.2218 22.374,362.2883 Q22.6509,362.3436 22.8835,362.4655 L22.8835,363.6063 Q22.6177,363.3627 22.3629,363.2519 Q22.1192,363.1411 21.8645,363.1411 Q21.2996,363.1411 21.0116,363.5842 Q20.7236,364.0272 20.7236,364.9023 Q20.7236,365.7773 21.0116,366.2203 Q21.2996,366.6634 21.8645,366.6634 Q22.1192,366.6634 22.3629,366.5526 Q22.6177,366.4419 22.8835,366.1982 L22.8835,367.339 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="94.9898" x="30.4818" y="367.7524">04 Address-ordered free list</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.4687" x2="126.8894" y1="374.9263" y2="374.9263"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="99.2431" x="17.0131" y="385.3397">previous &lt; inserted &lt; current</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="46.0772" x="17.0131" y="394.9946">A &lt; B &lt; C+tail</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.4687" x2="126.8894" y1="399.9071" y2="399.9071"/><!--MD5=[007d3a1820cefd008c8dbdad7e6fdec6]
class LEFT--><rect fill="#EDF6FA" height="50.5005" id="LEFT" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="131.8515" x="4.2533" y="458.7441"/><ellipse cx="21.1246" cy="468.6684" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M22.0329,471.0055 Q21.7892,471.1274 21.5233,471.1828 Q21.2575,471.2492 20.9585,471.2492 Q19.9173,471.2492 19.3635,470.5625 Q18.8207,469.8758 18.8207,468.5688 Q18.8207,467.2618 19.3635,466.575 Q19.9173,465.8883 20.9585,465.8883 Q21.2575,465.8883 21.5233,465.9548 Q21.8003,466.0102 22.0329,466.132 L22.0329,467.2728 Q21.767,467.0292 21.5123,466.9184 Q21.2686,466.8076 21.0138,466.8076 Q20.449,466.8076 20.161,467.2507 Q19.873,467.6937 19.873,468.5688 Q19.873,469.4438 20.161,469.8868 Q20.449,470.3299 21.0138,470.3299 Q21.2686,470.3299 21.5123,470.2191 Q21.767,470.1084 22.0329,469.8647 L22.0329,471.0055 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="94.9898" x="31.3325" y="471.4189">05 Previous / left neighbour</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="4.9622" x2="135.3959" y1="478.5928" y2="478.5928"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="123.345" x="8.5066" y="489.0062">previous + previous.size == inserted</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="68.7613" x="8.5066" y="498.6611">merge previous first</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="4.9622" x2="135.3959" y1="503.5736" y2="503.5736"/><!--MD5=[490fcd32b6546c9bc615869efabd094a]
class RIGHT--><rect fill="#EDF6FA" height="50.5005" id="RIGHT" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="122.6361" x="8.861" y="562.4106"/><ellipse cx="25.0943" cy="572.335" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M26.0026,574.672 Q25.7589,574.7939 25.4931,574.8493 Q25.2272,574.9157 24.9282,574.9157 Q23.887,574.9157 23.3332,574.229 Q22.7905,573.5423 22.7905,572.2353 Q22.7905,570.9283 23.3332,570.2415 Q23.887,569.5548 24.9282,569.5548 Q25.2272,569.5548 25.4931,569.6213 Q25.77,569.6767 26.0026,569.7985 L26.0026,570.9394 Q25.7367,570.6957 25.482,570.5849 Q25.2383,570.4741 24.9836,570.4741 Q24.4187,570.4741 24.1307,570.9172 Q23.8427,571.3602 23.8427,572.2353 Q23.8427,573.1103 24.1307,573.5533 Q24.4187,573.9964 24.9836,573.9964 Q25.2383,573.9964 25.482,573.8856 Q25.7367,573.7749 26.0026,573.5312 L26.0026,574.672 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="87.1922" x="35.1604" y="575.0854">06 Next / right neighbour</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="9.5699" x2="130.7882" y1="582.2593" y2="582.2593"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="114.1296" x="13.1143" y="592.6727">merged + merged.size == current</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="65.2169" x="13.1143" y="602.3276">merge next second</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="9.5699" x2="130.7882" y1="607.2402" y2="607.2402"/><path d="M152.409,367.1286 L152.409,377.4924 L127.9173,380.3279 L152.409,383.1634 L152.409,393.5272 A0,0 0 0 0 152.409,393.5272 L304.1092,393.5272 A0,0 0 0 0 304.1092,393.5272 L304.1092,374.2174 L297.0204,367.1286 L152.409,367.1286 A0,0 0 0 0 152.409,367.1286 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7088792948590754;"/><path d="M297.0204,367.1286 L297.0204,374.2174 L304.1092,374.2174 L297.0204,367.1286 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="124.7628" x="156.6623" y="378.2509">Address order exposes both physical</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="136.8137" x="156.6623" y="387.9058">neighbours without scanning the arena.</text><!--MD5=[fc2657b7de304bb41a5d36ac60748945]
reverse link HEADER to ALLOC--><path d="M70.1791,95.245 C70.1791,109.5006 70.1791,124.9329 70.1791,137.8557 " fill="none" id="HEADER&lt;-ALLOC" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,86.1926,67.3435,90.4459,70.1791,94.6992,73.0146,90.4459,70.1791,86.1926" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="60.2547" x="70.8879" y="114.4769">precedes payload</text><!--MD5=[bb73b5a7e21afff1a1d0c43dcbd5d11a]
link ALLOC to REM--><path d="M70.1791,198.4224 C70.1791,213.4506 70.1791,231.6688 70.1791,246.6687 " fill="none" id="ALLOC-&gt;REM" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,250.1422,73.0146,243.7623,70.1791,246.5978,67.3435,243.7623,70.1791,250.1422" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="46.0772" x="70.8879" y="227.7983">first-fit + split</text><!--MD5=[32aec76f28e14f88b0d74d9f592c80fb]
link REM to LIST--><path d="M70.1791,302.1243 C70.1791,316.5855 70.1791,334.9242 70.1791,350.1297 " fill="none" id="REM-&gt;LIST" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,353.667,73.0146,347.287,70.1791,350.1226,67.3435,347.287,70.1791,353.667" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="58.837" x="70.8879" y="331.4649">insert by address</text><!--MD5=[cc3605e5f4ba919f564e1d79e1300518]
link LIST to LEFT--><path d="M70.1791,405.7909 C70.1791,420.252 70.1791,438.5907 70.1791,453.7962 " fill="none" id="LIST-&gt;LEFT" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,457.3335,73.0146,450.9536,70.1791,453.7891,67.3435,450.9536,70.1791,457.3335" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="58.837" x="70.8879" y="435.1314">heap_4 tests first</text><!--MD5=[e8df39c6ef374d140d6cfa6fe0b5ac87]
link LEFT to RIGHT--><path d="M70.1791,509.4574 C70.1791,523.9185 70.1791,542.2572 70.1791,557.4627 " fill="none" id="LEFT-&gt;RIGHT" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,561,73.0146,554.6201,70.1791,557.4556,67.3435,554.6201,70.1791,561" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="51.7482" x="70.8879" y="538.7979">then tests next</text><!--MD5=[d8b34fb36bd2f73cd895320cbfc22e63]
@startuml
scale 620 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam classBorderColor #2c7794
skinparam classBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A2 STRUCTURE — RV32 header, split and two-sided coalescing
class "01 Block header" as HEADER {
next : BlockLink_t*
size : size_t
raw sizeof = 8 bytes on RV32
aligned xHeapStructSize = 16
}
class "Allocated block" as ALLOC {
02 A: header + 24 byte request
aligned total = 48 bytes
payload begins after header
}
class "03 Free remainder" as REM {
own header
free = 4032 bytes after A
}
HEADER *- - ALLOC : precedes payload
ALLOC -down-> REM : first-fit + split
class "04 Address-ordered free list" as LIST {
previous < inserted < current
A < B < C+tail
}
class "05 Previous / left neighbour" as LEFT {
previous + previous.size == inserted
merge previous first
}
class "06 Next / right neighbour" as RIGHT {
merged + merged.size == current
merge next second
}
REM -down-> LIST : insert by address
LIST -down-> LEFT : heap_4 tests first
LEFT -down-> RIGHT : then tests next
note right of LIST
Address order exposes both physical
neighbours without scanning the arena.
end note
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+29
View File
@@ -0,0 +1,29 @@
@startuml
scale 820 width
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A5 FLOW — eight deterministic Hazard3 replay states
rectangle "01 E01 RESET\n1 block · free=4080\nraw header=8 · aligned=16" as S1
rectangle "02 E02 ALLOC A(24)\nconsumed=48\nfree=4032" as S2
rectangle "03 E03 ALLOC B(40)\nconsumed=64\nfree=3968" as S3
rectangle "04 E04 ALLOC C(16)\nconsumed=32\nfree=3936" as S4
rectangle "05 E05 FREE A\n2 free blocks\nfree=3984" as S5
rectangle "06 E06 FREE C\n2 blocks · fragmented\nfree=4016" as S6
rectangle "07 E07 FREE B\nmerge left + right\n1 block · free=4080" as S7
rectangle "08 E08 OOM / VERIFY\nNULL · hook=1\nasserts=0 · PASS=1" as S8
S1 -right-> S2 : pvPortMalloc
S2 -right-> S3 : split remainder
S3 -right-> S4 : split remainder
S4 -down-> S5 : vPortFree(A)
S5 -left-> S6 : vPortFree(C)
S6 -left-> S7 : vPortFree(B)
S7 -left-> S8 : oversized request
@enduml
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="236.6008px" preserveAspectRatio="none" style="width:812px;height:236px;" version="1.1" viewBox="0 0 812 236" width="812.4374px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="239.8419" x="290.0791" y="10.3943">A5 FLOW — eight deterministic Hazard3 replay states</text><!--MD5=[d0cae5ff9305becd6f502d4fe4f41481]
entity S1--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="142.6087" x="6.4822" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="59.4203" x="17.2859" y="43.5704">01 E01 RESET</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="83.1884" x="17.2859" y="56.8136">1 block · free=4080</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="121.0013" x="17.2859" y="70.0569">raw header=8 · aligned=16</text><!--MD5=[d3395af3100fe8cebf35265100c4415f]
entity S2--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="110.1976" x="247.4045" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="88.5903" x="258.2082" y="43.5704">02 E02 ALLOC A(24)</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="63.7418" x="258.2082" y="56.8136">consumed=48</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="258.2082" y="70.0569">free=4032</text><!--MD5=[6c7192638421eaf134d201765ac5db29]
entity S3--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="110.1976" x="466.7194" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="88.5903" x="477.5231" y="43.5704">03 E03 ALLOC B(40)</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="63.7418" x="477.5231" y="56.8136">consumed=64</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="477.5231" y="70.0569">free=3968</text><!--MD5=[01b905ebe31ca24275b86a9951c478d0]
entity S4--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="110.1976" x="686.0343" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="88.5903" x="696.8379" y="43.5704">04 E04 ALLOC C(16)</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="63.7418" x="696.8379" y="56.8136">consumed=32</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="696.8379" y="70.0569">free=3936</text><!--MD5=[099bd2cf1f4f3a6dbf2f1fde6174f38e]
entity S5--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="84.2688" x="698.9987" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="62.6614" x="709.8024" y="184.861">05 E05 FREE A</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="56.1792" x="709.8024" y="198.1043">2 free blocks</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="709.8024" y="211.3475">free=3984</text><!--MD5=[0656c7721b015b9ca8cf2e2c2e8f5aee]
entity S6--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="118.8406" x="484.0053" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="62.6614" x="494.809" y="184.861">06 E06 FREE C</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="97.2332" x="494.809" y="198.1043">2 blocks · fragmented</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="494.809" y="211.3475">free=4016</text><!--MD5=[6ba532df225878998c5769132c3837e2]
entity S7--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="104.7958" x="282.5165" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="62.6614" x="293.3202" y="184.861">07 E07 FREE B</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="78.8669" x="293.3202" y="198.1043">merge left + right</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="83.1884" x="293.3202" y="211.3475">1 block · free=4080</text><!--MD5=[ce611cd767df6ac8a45071985dabb378]
entity S8--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="115.5995" x="46.996" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="93.9921" x="57.7997" y="184.861">08 E08 OOM / VERIFY</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="65.9025" x="57.7997" y="198.1043">NULL · hook=1</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="82.108" x="57.7997" y="211.3475">asserts=0 · PASS=1</text><!--MD5=[15cb110786dd224ca6a510a3d2a24e20]
link S1 to S2--><path d="M149.5014,53.044 C178.639,53.044 211.9792,53.044 240.0796,53.044 " fill="none" id="S1-&gt;S2" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="245.4706,53.044,235.7473,48.7226,240.0688,53.044,235.7473,57.3655,245.4706,53.044" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="58.3399" x="169.0777" y="46.1524">pvPortMalloc</text><!--MD5=[8eac89d31ced3c9003fbd6a8a005c745]
link S2 to S3--><path d="M358.1315,53.044 C389.0516,53.044 427.6208,53.044 459.5457,53.044 " fill="none" id="S2-&gt;S3" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="464.6126,53.044,454.8893,48.7226,459.2108,53.044,454.8893,57.3655,464.6126,53.044" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="69.1436" x="377.5889" y="46.1524">split remainder</text><!--MD5=[82e284a09e4ebade00512bdc77bff32c]
link S3 to S4--><path d="M577.4464,53.044 C608.3665,53.044 646.9357,53.044 678.8606,53.044 " fill="none" id="S3-&gt;S4" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="683.9275,53.044,674.2042,48.7226,678.5257,53.044,674.2042,57.3655,683.9275,53.044" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="69.1436" x="596.9038" y="46.1524">split remainder</text><!--MD5=[0e6b031b378ab8978eaa734a548bdfb6]
link S4 to S5--><path d="M741.1331,83.9642 C741.1331,105.2367 741.1331,133.9637 741.1331,156.6298 " fill="none" id="S4-&gt;S5" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="741.1331,161.8156,745.4545,152.0923,741.1331,156.4137,736.8116,152.0923,741.1331,161.8156" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="57.2596" x="742.2134" y="127.6015">vPortFree(A)</text><!--MD5=[3c9aaad44b43c509ca535c241fdd0151]
reverse link S6 to S5--><path d="M610.2356,194.3239 C639.492,194.3239 672.9618,194.3239 698.7286,194.3239 " fill="none" id="S6&lt;-S5" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="604.9202,194.3239,614.6435,198.6454,610.322,194.3239,614.6435,190.0024,604.9202,194.3239" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="57.2596" x="622.2925" y="187.4323">vPortFree(C)</text><!--MD5=[5f6ea4567bb0950bff1d27387d49b4c2]
reverse link S7 to S6--><path d="M394.7668,194.3239 C422.6403,194.3239 455.7212,194.3239 483.5947,194.3239 " fill="none" id="S7&lt;-S6" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="389.4406,194.3239,399.1639,198.6454,394.8424,194.3239,399.1639,190.0024,389.4406,194.3239" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="57.2596" x="407.029" y="187.4323">vPortFree(B)</text><!--MD5=[630b9631f886cf9c8b0d992525b86cf3]
reverse link S8 to S7--><path d="M169.8448,194.3239 C205.3025,194.3239 248.6253,194.3239 281.9871,194.3239 " fill="none" id="S8&lt;-S7" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="164.497,194.3239,174.2203,198.6454,169.8988,194.3239,174.2203,190.0024,164.497,194.3239" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="81.0277" x="182.0422" y="187.4323">oversized request</text><!--MD5=[9f7e06700e17220ce72e8c57ed6bc819]
@startuml
scale 820 width
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A5 FLOW — eight deterministic Hazard3 replay states
rectangle "01 E01 RESET\n1 block · free=4080\nraw header=8 · aligned=16" as S1
rectangle "02 E02 ALLOC A(24)\nconsumed=48\nfree=4032" as S2
rectangle "03 E03 ALLOC B(40)\nconsumed=64\nfree=3968" as S3
rectangle "04 E04 ALLOC C(16)\nconsumed=32\nfree=3936" as S4
rectangle "05 E05 FREE A\n2 free blocks\nfree=3984" as S5
rectangle "06 E06 FREE C\n2 blocks · fragmented\nfree=4016" as S6
rectangle "07 E07 FREE B\nmerge left + right\n1 block · free=4080" as S7
rectangle "08 E08 OOM / VERIFY\nNULL · hook=1\nasserts=0 · PASS=1" as S8
S1 -right-> S2 : pvPortMalloc
S2 -right-> S3 : split remainder
S3 -right-> S4 : split remainder
S4 -down-> S5 : vPortFree(A)
S5 -left-> S6 : vPortFree(C)
S6 -left-> S7 : vPortFree(B)
S7 -left-> S8 : oversized request
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+29
View File
@@ -0,0 +1,29 @@
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam stateBorderColor #2c7794
skinparam stateBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A6 STATE — reusable states of the same RV32 arena
[*] --> Free : 01 E01 one list node
Free --> Allocated : 02 E04 A+B+C allocated\ncurrent free = 3936
Allocated --> Fragmented : E05 free A\nE06 free C
Fragmented : 03 E06 two free blocks
Fragmented : sum free > largest block
Fragmented --> Coalesced : 04 E07 free B\nmerge previous, then next
Coalesced : one free block
Coalesced : current = largest = initial
Coalesced --> OOMChecked : 05 E08 request > arena
OOMChecked : NULL · hook=1 · PASS=1
OOMChecked --> [*]
state "minimum-ever" as MIN
Allocated -right-> MIN : records low watermark
Fragmented -right-> MIN : does not rise
Coalesced -right-> MIN : history remains
@enduml
+50
View File
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="600.2775px" preserveAspectRatio="none" style="width:321px;height:600px;" version="1.1" viewBox="0 0 321 600" width="321.3164px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="184.7569" x="70.8357" y="7.8065">A6 STATE — reusable states of the same RV32 arena</text><ellipse cx="193.155" cy="23.2954" fill="#000000" rx="7.3026" ry="7.3026" style="stroke: none; stroke-width: 0.7302646103274287;"/><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="36.5132" x="174.8984" y="85.3679"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="174.8984" x2="211.4116" y1="102.6168" y2="102.6168"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="15.3356" x="185.4872" y="96.8258">Free</text><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="47.4672" x="169.4214" y="186.8747"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="169.4214" x2="216.8886" y1="204.1235" y2="204.1235"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="32.8619" x="176.724" y="198.3325">Allocated</text><rect fill="#EDF6FA" height="44.4439" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="99.316" x="93.1087" y="288.3815"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="93.1087" x2="192.4247" y1="305.6303" y2="305.6303"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="42.3553" x="121.5891" y="299.8393">Fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="79.5988" x="96.7601" y="317.0882">03 E06 two free blocks</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="84.7107" x="96.7601" y="327.0344">sum free &gt; largest block</text><rect fill="#EDF6FA" height="44.4439" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="102.9673" x="4.3816" y="397.8189"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="4.3816" x2="107.3489" y1="415.0678" y2="415.0678"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="35.783" x="37.9738" y="409.2768">Coalesced</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="49.658" x="8.0329" y="426.5256">one free block</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="88.362" x="8.0329" y="436.4718">current = largest = initial</text><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="96.3949" x="7.6678" y="497.0327"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="7.6678" x2="104.0627" y1="514.2815" y2="514.2815"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="47.4672" x="32.1316" y="508.4905">OOMChecked</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="81.7896" x="11.3191" y="525.7394">NULL · hook=1 · PASS=1</text><ellipse cx="55.8652" cy="585.3947" fill="none" rx="7.3026" ry="7.3026" style="stroke: #000000; stroke-width: 0.7302646103274287;"/><ellipse cx="56.2304" cy="585.7598" fill="#000000" rx="4.3816" ry="4.3816" style="stroke: none; stroke-width: 0.7302646103274287;"/><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="64.9936" x="188.4083" y="401.7843"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="188.4083" x2="253.4018" y1="419.0331" y2="419.0331"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="50.3883" x="195.7109" y="413.2421">minimum-ever</text><!--MD5=[f16808fa220dde377303612249059854]
link *start to Free--><path d="M193.155,30.7514 C193.155,41.647 193.155,63.6352 193.155,80.4898 " fill="none" id="*start-&gt;Free" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="193.155,83.9877,196.076,77.4153,193.155,80.3364,190.2339,77.4153,193.155,83.9877" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="72.2962" x="193.8853" y="61.0428">01 E01 one list node</text><!--MD5=[19abaf48dc778410378e95e0d1bca006]
link Free to Allocated--><path d="M193.155,122.239 C193.155,138.9547 193.155,163.9809 193.155,182.0111 " fill="none" id="Free-&gt;Allocated" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="193.155,185.5675,196.076,178.9951,193.155,181.9162,190.2339,178.9951,193.155,185.5675" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="83.9804" x="193.8853" y="152.3259">02 E04 A+B+C allocated</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="67.9146" x="201.9182" y="162.2721">current free = 3936</text><!--MD5=[f6fa3e1917b73de38ea03346a6903b17]
link Allocated to Fragmented--><path d="M184.4941,223.7385 C176.4611,240.3228 164.4191,265.181 155.3346,283.9342 " fill="none" id="Allocated-&gt;Fragmented" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="153.8083,287.0889,159.2954,282.4391,155.3952,283.8004,154.0338,279.9002,153.8083,287.0889" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="35.783" x="174.6866" y="253.8327">E05 free A</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="35.783" x="174.6866" y="263.7789">E06 free C</text><!--MD5=[c73bca393b062d6a86dff80fa900c78c]
link Fragmented to Coalesced--><path d="M92.7509,329.6414 C81.6363,335.9582 71.0474,344.1883 63.8982,354.7333 C56.391,365.8114 54.1053,380.4606 53.8278,393.0065 " fill="none" id="Fragmented-&gt;Coalesced" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="53.8132,396.4241,56.753,389.8601,53.8236,392.7728,50.9109,389.8434,53.8132,396.4241" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="47.4672" x="87.2666" y="363.2701">04 E07 free B</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="92.7436" x="64.6284" y="373.2163">merge previous, then next</text><!--MD5=[2b306524d92469efb3bb270d490680cf]
link Coalesced to OOMChecked--><path d="M55.8652,442.5257 C55.8652,457.3647 55.8652,476.9796 55.8652,491.9939 " fill="none" id="Coalesced-&gt;OOMChecked" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="55.8652,495.5941,58.7863,489.0217,55.8652,491.9427,52.9442,489.0217,55.8652,495.5941" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="82.5199" x="56.5955" y="472.7076">05 E08 request &gt; arena</text><!--MD5=[6b8be85e17f6174335a5329fe1414850]
link OOMChecked to *end--><path d="M55.8652,533.6993 C55.8652,546.2379 55.8652,562.6835 55.8652,573.4622 " fill="none" id="OOMChecked-&gt;*end" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="55.8652,576.8725,58.7863,570.3001,55.8652,573.2212,52.9442,570.3001,55.8652,576.8725" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><!--MD5=[b09143a670c8c67aa163b99fca5c6b6b]
link Allocated to MIN--><path d="M206.402,223.6581 C210.5791,230.1502 214.7489,237.7595 217.2537,245.2959 C235.6199,300.555 231.8517,317.8477 227.4774,375.911 C226.9589,382.7609 225.995,390.1731 224.958,396.8988 " fill="none" id="Allocated-&gt;MIN" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="224.403,400.3384,228.3223,394.3078,224.9778,396.7326,222.5531,393.3881,224.403,400.3384" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="81.0594" x="231.8006" y="313.6632">records low watermark</text><!--MD5=[1fa23b8554d20d5dd3f2f8930c0e2df3]
link Fragmented to MIN--><path d="M152.2237,332.9422 C158.409,345.9702 167.1649,362.5618 177.0892,375.911 C182.9094,383.7394 190.1317,391.4875 197.0254,398.2279 " fill="none" id="Fragmented-&gt;MIN" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="199.5813,400.6889,196.8641,394.0296,196.9477,398.1598,192.8176,398.2434,199.5813,400.6889" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="46.0067" x="177.8194" y="368.382">does not rise</text><!--MD5=[87522a40b34d64237ec6603d41372cd8]
link Coalesced to MIN--><path d="M107.6337,420.0409 C132.2582,420.0409 161.1402,420.0409 183.5812,420.0409 " fill="none" id="Coalesced-&gt;MIN" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="187.1595,420.0409,180.5871,417.1198,183.5082,420.0409,180.5871,422.962,187.1595,420.0409" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="54.7698" x="120.4937" y="415.4329">history remains</text><!--MD5=[ca62bd85e5915d2f6639cfa0fa77f8b6]
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam stateBorderColor #2c7794
skinparam stateBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A6 STATE — reusable states of the same RV32 arena
[*] - -> Free : 01 E01 one list node
Free - -> Allocated : 02 E04 A+B+C allocated\ncurrent free = 3936
Allocated - -> Fragmented : E05 free A\nE06 free C
Fragmented : 03 E06 two free blocks
Fragmented : sum free > largest block
Fragmented - -> Coalesced : 04 E07 free B\nmerge previous, then next
Coalesced : one free block
Coalesced : current = largest = initial
Coalesced - -> OOMChecked : 05 E08 request > arena
OOMChecked : NULL · hook=1 · PASS=1
OOMChecked - -> [*]
state "minimum-ever" as MIN
Allocated -right-> MIN : records low watermark
Fragmented -right-> MIN : does not rise
Coalesced -right-> MIN : history remains
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+23
View File
@@ -0,0 +1,23 @@
@startuml
scale 820 width
left to right direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A7 RUNTIME — source identity, replay, memory and verdict
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
rectangle "<<checkpoint E06>>\n03 fragmented\nblocks=2 · free>largest" as E1
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
rectangle "<<checkpoint E08>>\n05 verified\nfinal=initial · blocks=1\nOOM=1 · PASS=1" as E2
SRC --> ELF : compile + link
ELF --> E1 : reset / load / replay
E1 --> MEM : inspect bytes
MEM --> E2 : continue
@enduml
+44
View File
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="82px" preserveAspectRatio="none" style="width:814px;height:82px;" version="1.1" viewBox="0 0 814 82" width="814.26px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="204.18" x="307.91" y="7.8893">A7 RUNTIME — source identity, replay, memory and verdict</text><!--MD5=[183d75e42a7a852d02a7f9ce2cc3343f]
entity SRC--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="77.9" x="4.92" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="31.16" x="13.12" y="37.7029">«source»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="38.54" x="13.12" y="47.7545">01 task03 C</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="61.5" x="13.12" y="57.8062">A/B/C experiment</text><!--MD5=[4a7b087cd571ae358eb895b9dc7ce0ed]
entity ELF--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="71.34" x="179.58" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="31.98" x="187.78" y="37.7029">«artifact»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="50.84" x="187.78" y="47.7545">02 ELF + image</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="54.94" x="187.78" y="57.8062">heap_4 symbols</text><!--MD5=[45565a74ca8123df0b8413ce5340d40a]
entity E1--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="92.66" x="367.36" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="59.86" x="375.56" y="37.7029">«checkpoint E06»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="51.66" x="375.56" y="47.7545">03 fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="76.26" x="375.56" y="57.8062">blocks=2 · free&gt;largest</text><!--MD5=[5ceda9279414f57783e95166b8d927b7]
entity MEM--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="80.36" x="555.96" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="36.9" x="564.16" y="37.7029">«memory»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="58.22" x="564.16" y="47.7545">04 ucHeap[4096]</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="63.96" x="564.16" y="57.8062">headers + payload</text><!--MD5=[a3c437a7ee715155cf6a0fec80d7cbaf]
entity E2--><rect fill="#EDF6FA" height="56.6065" style="stroke: #2C7794; stroke-width: 1.23;" width="87.74" x="717.5" y="16.587"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="59.86" x="725.7" y="32.6763">«checkpoint E08»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="36.08" x="725.7" y="42.7279">05 verified</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="71.34" x="725.7" y="52.7796">final=initial · blocks=1</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="56.58" x="725.7" y="62.8312">OOM=1 · PASS=1</text><!--MD5=[2e73c4d4efa4a7715d66b06010e70f85]
link SRC to ELF--><path d="M83.2054,44.8852 C110.372,44.8852 146.6734,44.8852 174.209,44.8852 " fill="none" id="SRC-&gt;ELF" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="178.0056,44.8852,170.6256,41.6052,173.9056,44.8852,170.6256,48.1652,178.0056,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="45.92" x="108.24" y="42.1145">compile + link</text><!--MD5=[98439561a91d683361f6e8599ebb304f]
link ELF to E1--><path d="M251.2562,44.8852 C282.0636,44.8852 327.221,44.8852 361.9726,44.8852 " fill="none" id="ELF-&gt;E1" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="365.9988,44.8852,358.6188,41.6052,361.8988,44.8852,358.6188,48.1652,365.9988,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="65.6" x="276.34" y="42.1145">reset / load / replay</text><!--MD5=[14b84038a04448f34eb55bd119f2d935]
link E1 to MEM--><path d="M460.3726,44.8852 C488.0476,44.8852 523.1518,44.8852 550.6136,44.8852 " fill="none" id="E1-&gt;MEM" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="554.4102,44.8852,547.0302,41.6052,550.3102,44.8852,547.0302,48.1652,554.4102,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="45.1" x="485.44" y="42.1145">inspect bytes</text><!--MD5=[28f0a5a321106494a7afb95cbc1e35b0]
link MEM to E2--><path d="M636.5578,44.8852 C659.3374,44.8852 688.1276,44.8852 712.2274,44.8852 " fill="none" id="MEM-&gt;E2" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="716.0568,44.8852,708.6768,41.6052,711.9568,44.8852,708.6768,48.1652,716.0568,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="30.34" x="661.74" y="42.1145">continue</text><!--MD5=[d3cc7590ea240485cc9ae283b10caa4d]
@startuml
scale 820 width
left to right direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A7 RUNTIME — source identity, replay, memory and verdict
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
rectangle "<<checkpoint E06>>\n03 fragmented\nblocks=2 · free>largest" as E1
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
rectangle "<<checkpoint E08>>\n05 verified\nfinal=initial · blocks=1\nOOM=1 · PASS=1" as E2
SRC - -> ELF : compile + link
ELF - -> E1 : reset / load / replay
E1 - -> MEM : inspect bytes
MEM - -> E2 : continue
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

+190
View File
@@ -0,0 +1,190 @@
# FC01 — FreeRTOS `heap_4`: od kursora do wolnych bloków
## Decyzja dydaktyczna
To jest jedna 30-minutowa lekcja i bezpośrednia kontynuacja projektu
K&R 5.4 z karty C07. Karta nie uczy pięciu implementacji heap jako pięciu
równorzędnych tematów. `heap_1`, `heap_2`, `heap_3` i `heap_5` zajmują łącznie
maksymalnie minutę kontekstu. Cała właściwa praca dotyczy `heap_4`.
Task 1 i Task 2 są krótkimi modelami prowadzonymi przez nauczyciela. Uczeń
najpierw zapisuje predykcję, ale nie buduje i nie debugguje tych programów
osobno podczas lekcji. Task 3, linkujący upstream `heap_4.c`, jest jedynym
centralnym przebiegiem ucznia.
## Stan wejściowy z K&R 5.4
Uczeń przychodzi z działającym kodem:
```text
allocbuf[64]
allocp
allocator_reset()
alloc_local(5) -> offset 0
alloc_local(7) -> offset 5
allocp -> offset 12
alloc_local(0) oraz OOM -> NULL bez przesunięcia kursora
```
Nie powtarzamy sposobu działania tego kodu. Zaczynamy od jego granicy:
> Jak zwolnić obszar 5 B spod offsetu 0, zachować późniejszy obszar 7 B spod
> offsetu 5 i ponownie wykorzystać powstałą dziurę?
W projekcie nie istnieje operacja zwolnienia pojedynczego obszaru. Nawet proste
cofnięcie kursora unieważniłoby wszystkie późniejsze przydziały. Brakuje
tożsamości bloku, jego rozmiaru, zbioru dziur i mechanizmu ich łączenia.
## Cel w jednym zdaniu
Po 30 minutach uczeń potrafi wyjaśnić i pokazać w debuggerze, jak `heap_4`
dodaje do liniowej areny nagłówki, wybór first-fit, podział bloku, listę wolnych
bloków oraz scalanie sąsiadów, a następnie odróżnić bieżącą ilość wolnej
pamięci, największy wolny blok i minimum-ever.
## Most K&R 5.4 -> `heap_4`
| K&R 5.4 — stan projektu | Ograniczenie | `heap_4` — nowy mechanizm |
| --- | --- | --- |
| `allocbuf[64]` i jeden `allocp` | istnieje tylko wolny ogon areny | `ucHeap[]` i bloki opisane nagłówkami |
| wynik to surowy adres | allocator nie zna później rozmiaru obszaru | `BlockLink_t` przed payloadem przechowuje rozmiar |
| kolejne przydziały tylko przesuwają kursor | nie można użyć dziury | lista wolnych bloków i wybór first-fit |
| brak zwalniania pojedynczego obszaru | reset odzyskuje wszystko naraz | `vPortFree()` odzyskuje wskazany blok |
| brak relacji między dziurami | sąsiednie dziury pozostają rozdzielone | porządek adresowy i coalescing w obie strony |
| tylko sukces albo `NULL` | brak informacji o fragmentacji | free, largest, liczba bloków i minimum-ever |
W realnym `heap_4.c` najwyższy bit `xBlockSize` oznacza blok przydzielony.
Uproszczone modele Task 12 pokazują geometrię i listę, ale nie odtwarzają tego
bitu. To jawna granica modelu.
## Przygotowanie przed lekcją
Budowanie, flashowanie i wykrywanie debug probe nie wchodzą do budżetu 30 minut.
Przed wejściem uczniów:
1. zbuduj Task 3 dla `pico2_w` / RP2350 RISC-V;
2. wgraj zweryfikowany obraz i otwórz sesję na tym samym ELF;
3. ustaw pierwszy breakpoint na `heap4_reset_checkpoint`;
4. przygotuj widok `ucHeap`, statystyk E01--E08,
`xFreeBytesRemaining` i `xMinimumEverFreeBytesRemaining`;
5. przygotuj Hazard3 jako awaryjny zamiennik — podczas lekcji użyj jednej
platformy, nigdy obu.
`heap_4` jest implementacją wybraną i linkowaną przez projekt. Nie jest
sprzętowym heapem ani peryferium RP2350.
## Przebieg 30 minut
| Czas | Tryb | Działanie i dowód |
| --- | --- | --- |
| 03 min | problem | Przypomnij wyłącznie offsety `0 -> 5 -> 12`. Uczeń próbuje zwolnić pierwszy obszar bez utraty drugiego i nazywa brakującą operację. |
| 34 min | kontekst | Jedno zdanie: FreeRTOS dostarcza wymienne implementacje tego samego API; ta karta i oficjalne przykłady Pico 2 W linkują `heap_4`. |
| 49 min | Task 1 — demo | Do żądania dodaj nagłówek, wyrównaj rozmiar, wybierz pierwszy pasujący blok i podziel go. Uczeń zapisuje `wanted` i `remainder` przed odsłonięciem wyniku. |
| 916 min | Task 2 — demo | Dla `A:48 | B:48 | C:48` pokaż listę `A -> C`, wstaw `B` po adresie i sprawdź scalenie w prawo oraz w lewo: `2 bloki / 96 B / largest 48 B -> 1 blok / 144 B / largest 144 B`. |
| 1627 min | Task 3 — RUN | Na przygotowanym celu przejdź przez osiem checkpointów prawdziwego `heap_4.c`: reset, trzy alokacje, free A, free C, free B i kontrolowany OOM. Uczeń wypełnia tabelę relacji. |
| 2730 min | wyjście | Uczeń wymienia trzy dodatki ponad K&R (`header`, `free list`, `coalescing`) i wyjaśnia: suma wolnych bajtów może być większa od największego bloku, a minimum-ever nie rośnie po `free`. |
## Task 1 — model nagłówka i splitu
Task 1 nie jest osobnym laboratorium. Na RV32 nagłówek modelu ma 8 B, więc
żądanie 13 B daje `wanted=24 B` i `remainder=232 B` z areny 256 B. Na AMD64
odpowiednie wartości to 16 B, 32 B i 224 B. Różnica ABI jest tylko pomocą w
zrozumieniu `sizeof` i wyrównania; podczas głównego przebiegu obowiązuje RP2350.
Predykcja ucznia:
```text
free list: [16 B] -> [80 B] -> [160 B]
request + header po wyrównaniu: 24 B
first-fit wybiera: __________
po split: allocated ______ B, remainder ______ B
```
Wykonywalny Task 1 dowodzi obecnie geometrii splitu jednego bloku. Samo
przeszukanie dwóch kandydatów jest elementem demonstracji i realnego
`pvPortMalloc()`, dlatego nie opisujemy Task 1 jako pełnego testu first-fit.
## Task 2 — model listy adresowej i coalescingu
```text
pamięć: [ A:48 FREE ][ B:48 USED ][ C:48 FREE ]
free list: A --------------------------------> C
vPortFree(B)
1. wstaw B pomiędzy A i C według adresu;
2. jeśli end(A) == addr(B), połącz A+B;
3. jeśli end(AB) == addr(C), połącz AB+C;
wynik: [ ABC:144 FREE ]
free list: A -> END
```
Uczeń przed odsłonięciem rysuje listę i wpisuje `2 -> 1`, `96 -> 144` oraz
`48 -> 144` odpowiednio dla liczby bloków, sumy i largest.
## Task 3 — centralny przebieg upstream `heap_4.c`
```text
RESET/INIT
-> heap4_reset_checkpoint # E01: 4080 B
-> ALLOC A(24)
-> heap4_alloc_a_checkpoint # E02: 4032 B
-> ALLOC B(40)
-> heap4_alloc_b_checkpoint # E03: 3968 B
-> ALLOC C(16)
-> heap4_alloc_c_checkpoint # E04: 3936 B
-> FREE A
-> heap4_free_a_checkpoint # E05: 3984 B, 2 bloki
-> FREE C
-> heap4_fragmented_checkpoint # E06: 4016 B, 2 bloki
-> FREE B
-> heap4_coalesced_checkpoint # E07: 4080 B, 1 blok
-> OOM request
-> task03_debug_checkpoint # E08: NULL, hook=1, pass=1
```
Na Hazard3 `sizeof(BlockLink_t)=8`, ale `portBYTE_ALIGNMENT=16`, dlatego
`xHeapStructSize=16`. Główny replay ma stałe, testowane wartości:
| Obserwacja | Oczekiwany wynik RV32/Hazard3 |
| --- | --- |
| E01--E04 | `4080 -> 4032 -> 3968 -> 3936`, zużycie `48/64/32` |
| E05--E06 | `3984 -> 4016`, nadal 2 bloki i `largest < total_free` |
| E07 | `final_free == initial_free == 4080`, `free_blocks == 1` |
| low-water mark | `minimum_ever == 3936` i nie rośnie po free |
| OOM | wynik `NULL`, hook `1`, brak uszkodzenia listy |
Minimalny dowód w GDB:
```gdb
p g_fragmented_stats
p g_final_stats
p g_a_consumed
p g_b_consumed
p g_c_consumed
p xFreeBytesRemaining
p xMinimumEverFreeBytesRemaining
p xStart
p pxEnd
x/96bx ucHeap
```
Szczegółowe mapowanie wszystkich diagramów do kodu, replay i dowodów zawiera
[`hazard3-iteration-plan.md`](hazard3-iteration-plan.md).
## Kryterium zaliczenia
Uczeń zalicza lekcję, jeżeli:
- wskaże, dlaczego jeden kursor nie wystarcza do zwolnienia obszaru ze środka;
- rozróżni nagłówek allocatora od payloadu i stosu `sp`;
- przewidzi przejście wolnej listy `2 -> 1` po zwolnieniu B;
- wyjaśni różnicę `total free` kontra `largest free block`;
- wyjaśni, dlaczego minimum-ever nie wraca po `free`;
- pokaże `aligned=1 oom=1 hooks=1 asserts=0 pass=1` w Task 3.
## Poza lekcją
Jako rozszerzenie lub pracę własną pozostają: pełne czytanie `heap_4.c`,
uruchomienie Task 12 na AMD64 i Hazard3, samodzielny deploy RP2350 oraz
porównanie z `heap_1`, `heap_2`, `heap_3` i `heap_5`.
+340
View File
@@ -0,0 +1,340 @@
% Generated from json/card_source.json by tools/render_card.py.
% Do not edit manually; update the JSON and regenerate.
\documentclass[12pt,a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[utf8]{inputenc}
\usepackage[polish]{babel}
\usepackage{csquotes}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{xcolor}
\usepackage[a4paper,left=2.15cm,right=2.15cm,top=0.5cm,bottom=1cm,headheight=24mm,headsep=3mm,includehead,includefoot]{geometry}
\usepackage{eso-pic}
\usepackage{marginnote}
\usepackage{array}
\usepackage{tabularx}
\usepackage{graphicx}
\usepackage{pdflscape}
\usepackage{float}
\usepackage{silence}
\WarningFilter{soulutf8}{This package is obsolete}
\usepackage{pdfcomment}
\usepackage{enumitem}
\usepackage{needspace}
\usepackage{fancyhdr}
\usepackage{lastpage}
\usepackage{microtype}
\usepackage[most]{tcolorbox}
\usepackage{qrcode}
\IfFileExists{references.bib}{%
\usepackage[backend=biber,style=numeric,sorting=none]{biblatex}%
\addbibresource{references.bib}%
}{}
\hypersetup{hidelinks}
\IfFileExists{build-meta.tex}{%
\input{build-meta.tex}%
}{%
\newcommand{\BuildCommit}{lokalna}%
}
\newcommand{\DocumentAuthor}{Mateusz Pabiszczak}
\newcommand{\DocumentYear}{2026}
\newcommand{\CardSeries}{freertos-c}
\newcommand{\CardSeriesTitle}{FreeRTOS C}
\newcommand{\CardNumber}{01}
\newcommand{\CardCount}{15}
\newcommand{\CardSlug}{heap4-mechanics}
\newcommand{\CardVersion}{v00.01}
\newcommand{\CardStatus}{Gotowa}
\newcommand{\DocumentUUID}{87e48095-7793-54e3-9230-4e61d31bd459}
\newcommand{\EmptyCheck}{\(\square\)}
\newcommand{\EscAnswerLines}[1][3]{\par\noindent\dotfill\par\noindent\dotfill\par\noindent\dotfill}
\newcommand{\EscWriteRow}[1][2.8em]{\rule{0pt}{#1}}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0.45em}
\setlength{\headheight}{24mm}
\setlength{\headsep}{3mm}
\setlength{\footskip}{8mm}
\setlength{\marginparwidth}{1.5cm}
\setlength{\marginparsep}{0.25cm}
\renewcommand{\arraystretch}{1.22}
% Margin separator lines disabled for layout trial.
\newcommand{\ESCPageResourceHeader}{%
\begingroup%
\setlength{\parskip}{0pt}%
\setlength{\fboxsep}{0pt}%
\setlength{\fboxrule}{0.35pt}%
\setlength{\arrayrulewidth}{0.35pt}%
\noindent\fbox{%
\begin{minipage}[c][23.5mm][c]{\dimexpr\textwidth-2\fboxrule\relax}%
\begin{minipage}[c][23mm][c]{24mm}\centering%
\href{https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-heap4}{\qrcode[level=L,height=22mm]{https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-heap4}}%
\end{minipage}%
\vrule width0.35pt%
\begin{minipage}[c][23mm][c]{\dimexpr\linewidth-48mm-0.7pt\relax}%
\setlength{\tabcolsep}{0pt}%
\renewcommand{\arraystretch}{0}%
\begin{tabularx}{\linewidth}{@{}p{\dimexpr0.50000000\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.15126050\linewidth-\arrayrulewidth\relax}|X@{}}%
\parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries TITLE}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{7.7}{7.9}\selectfont\ttfamily\bfseries heap\_4: From Linear Cursor to Reusable Blocks}\hspace{0.45mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries VER.}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{6.6}{6.8}\selectfont\ttfamily\bfseries v00.01}\hspace{0.45mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries DATETIME}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{6.4}{6.6}\selectfont\ttfamily\bfseries 2026-07-20T00:00:00+02:00}\hspace{0.45mm}}\par} \\%
\end{tabularx}%
\par\nointerlineskip%
\hrule height0.35pt%
\nointerlineskip%
\begin{tabularx}{\linewidth}{@{}p{\dimexpr0.50000000\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.25210084\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.14285714\linewidth-\arrayrulewidth\relax}|X@{}}%
\parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries PROJECT}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{7.7}{7.9}\selectfont\ttfamily\bfseries Freestanding C nad FreeRTOS}\hspace{0.45mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries SERIES}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{6.4}{6.6}\selectfont\ttfamily\bfseries FreeRTOS C}\hspace{0.45mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries CARD}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{6.4}{6.6}\selectfont\ttfamily\bfseries 01/15}\hspace{0.45mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{3.2}{3.4}\selectfont\ttfamily\bfseries SHEET}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{6.4}{6.6}\selectfont\ttfamily\bfseries \thepage/\pageref{LastPage}}\hspace{0.45mm}}\par} \\%
\end{tabularx}%
\par\nointerlineskip%
\hrule height0.35pt%
\nointerlineskip%
\begin{tabularx}{\linewidth}{@{}p{\dimexpr0.05882353\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.05042017\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.14705882\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.09243697\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.07563025\linewidth-\arrayrulewidth\relax}|p{\dimexpr0.07563025\linewidth-\arrayrulewidth\relax}|X@{}}%
\parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.15mm}{\fontsize{2.85}{3}\selectfont\ttfamily\bfseries SUBJ.}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{4.45}{4.65}\selectfont\ttfamily\bfseries Inf.}\hspace{0.15mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.15mm}{\fontsize{2.85}{3}\selectfont\ttfamily\bfseries PROG.}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{4.45}{4.65}\selectfont\ttfamily\bfseries}\hspace{0.15mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.15mm}{\fontsize{2.85}{3}\selectfont\ttfamily\bfseries CORE}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{4.45}{4.65}\selectfont\ttfamily\bfseries}\hspace{0.15mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.15mm}{\fontsize{2.85}{3}\selectfont\ttfamily\bfseries SCOPE}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{4.45}{4.65}\selectfont\ttfamily\bfseries}\hspace{0.15mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.15mm}{\fontsize{2.85}{3}\selectfont\ttfamily\bfseries LEVEL}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{4.45}{4.65}\selectfont\ttfamily\bfseries}\hspace{0.15mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hspace{0.15mm}{\fontsize{2.85}{3}\selectfont\ttfamily\bfseries POS.}\par\nointerlineskip\vspace{0.12mm}\noindent\makebox[\linewidth][r]{{\fontsize{4.45}{4.65}\selectfont\ttfamily\bfseries}\hspace{0.15mm}}\par} & \parbox[c][5.19414mm][c]{\linewidth}{\hbox to\linewidth{\hspace{0.35mm}{\fontsize{3.4}{3.75}\selectfont\ttfamily\bfseries GITEA UUID}\hfill{\fontsize{3.4}{3.75}\selectfont\ttfamily 87e48095-7793-54e3-9230-4e61d31bd459}\hspace{0.35mm}}\par\nointerlineskip\hbox to\linewidth{\hspace{0.35mm}{\fontsize{3.4}{3.75}\selectfont\ttfamily\bfseries CARD UUID} {\fontsize{3.4}{3.75}\selectfont\ttfamily aea09ab7-9bfd-5368-8d1b-c8724871c1a7}\hfill{\fontsize{3.4}{3.75}\selectfont\ttfamily\bfseries AUTHOR Mateusz Pabiszczak}\hspace{0.35mm}}} \\%
\end{tabularx}%
\par\nointerlineskip%
\hrule height0.35pt%
\nointerlineskip%
\begin{tabularx}{\linewidth}{@{}X@{}}%
\parbox[c][3.46276mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{4.5}{4.85}\selectfont\ttfamily\bfseries GITEA} {\fontsize{4.5}{4.85}\selectfont\ttfamily\href{https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-heap4}{\nolinkurl{https://zsl-gitea.mpabi.pl/edu-freertos-c/lab-rv32i-freertos-heap4}}}} \\%
\end{tabularx}%
\par\nointerlineskip%
\hrule height0.35pt%
\nointerlineskip%
\begin{tabularx}{\linewidth}{@{}X@{}}%
\parbox[c][3.46276mm][c]{\linewidth}{\hspace{0.45mm}{\fontsize{4.5}{4.85}\selectfont\ttfamily\bfseries HTML} {\fontsize{4.5}{4.85}\selectfont\ttfamily\href{https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/aea09ab7-9bfd-5368-8d1b-c8724871c1a7}{\nolinkurl{https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/aea09ab7-9bfd-5368-8d1b-c8724871c1a7}}}} \\%
\end{tabularx}%
\end{minipage}%
\vrule width0.35pt%
\begin{minipage}[c][23mm][c]{24mm}\centering%
\href{https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/aea09ab7-9bfd-5368-8d1b-c8724871c1a7}{\qrcode[level=L,height=22mm]{https://dce7fb9d-7b2f-5d49-96a2-3a30d3070b84.mpabi.pl/aea09ab7-9bfd-5368-8d1b-c8724871c1a7}}%
\end{minipage}%
\end{minipage}%
}%
\endgroup%
}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[C]{\ESCPageResourceHeader}
\fancyfoot[L]{{\fontsize{6.4}{7.0}\selectfont\ttfamily UUID \DocumentUUID}}
\fancyfoot[C]{{\fontsize{6.4}{7.0}\selectfont\ttfamily \DocumentAuthor}}
\fancyfoot[R]{{\fontsize{6.4}{7.0}\selectfont\ttfamily STRONA \thepage/\pageref{LastPage}}}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0.35pt}
\newcommand{\ESCMarginTag}[4]{%
\hspace*{#1}\textcolor{#2}{#3~#4}%
}
\newcommand{\ESCSectionBlockStart}{%
\Needspace{8\baselineskip}%
\par\vspace{0.35em}%
\noindent\textcolor{black!28}{\rule{\textwidth}{0.35pt}}%
\par\vspace{0.15em}%
}
\newcommand{\ESCSectionBlockEnd}{%
\par\vspace{0.45em}%
}
\newcommand{\ESCTinyStepSeparator}{%
\par\vspace{0.10em}%
\noindent{\color{black!18}\leaders\hbox{\rule{0.60em}{0.22pt}\hspace{0.38em}}\hfill\kern0pt}%
\par\vspace{0.10em}%
}
\newtcolorbox{ESCTaskFrame}[1]{enhanced,breakable,arc=0pt,boxrule=0.35pt,colback=white,colframe=black,boxsep=0pt,left=1.4mm,right=1.4mm,top=0.8mm,bottom=0.8mm,colbacktitle=black!7,coltitle=black,title={\ttfamily\bfseries TASK\quad #1}}
\newtcolorbox{ESCBlockFrame}[1]{enhanced,breakable,arc=0pt,boxrule=0.35pt,colback=white,colframe=black!55,boxsep=0pt,left=1.0mm,right=1.0mm,top=0.6mm,bottom=0.6mm,colbacktitle=black!4,coltitle=black,title={\ttfamily\bfseries BLOCK\quad #1}}
\newtcolorbox{ESCStepFrame}[1]{enhanced,breakable,arc=0pt,boxrule=0.35pt,colback=white,colframe=black!28,boxsep=0pt,left=0.8mm,right=0.8mm,top=0.45mm,bottom=0.45mm,colbacktitle=black!2,coltitle=black,title={\ttfamily STEP\quad #1}}
\newtcolorbox{ESCConclusionFrame}{enhanced,breakable,arc=0pt,boxrule=0.45pt,colback=blue!2,colframe=blue!45!black,boxsep=0pt,left=1.2mm,right=1.2mm,top=0.7mm,bottom=0.7mm,colbacktitle=blue!7,coltitle=black,title={\ttfamily\bfseries WNIOSEK}}
\newcommand{\ESCLearningTreeWidget}{%
\reversemarginpar
\marginnote[%
\begin{minipage}{\marginparwidth}%
\raggedright
{\fontsize{3.55}{3.95}\selectfont\ttfamily
\begin{minipage}[t]{\marginparwidth}%
\raggedright
{\bfseries\textcolor{black!65}{TECH}\par}%
\vspace{0.08em}%
\hspace*{0.00em}\textcolor{red}{WE~01}\textcolor{black!48}{}\par%
\hspace*{0.28em}\textcolor{orange!85!black}{EK~LOCAL~RTOS}\textcolor{black!48}{\pdftooltip[width=\textwidth]{.01}{Uczeń odtwarza osiem checkpointów Hazard3 i odróżnia current free, largest free block oraz\textCR minimum-ever.}}\par%
\hspace*{0.54em}\textcolor{blue!70!black}{KW~LOCAL~RTOS}\textcolor{black!48}{\pdftooltip[width=\textwidth]{.01}{Łączy kod, diagram i zweryfikowany dowód.}}\par%
\end{minipage}%
}%
\end{minipage}%
]{}
\normalmarginpar
\marginnote{%
\begin{minipage}{\marginparwidth}%
\raggedright
{\fontsize{3.55}{3.95}\selectfont\ttfamily
\hspace*{0.06cm}%
\begin{minipage}[t]{\dimexpr\marginparwidth-0.06cm\relax}%
\raggedright
{\bfseries\textcolor{black!65}{OG}\par}%
\vspace{0.08em}%
\hspace*{0.00em}\textcolor{red}{WE~01}\textcolor{black!48}{}\par%
\hspace*{0.28em}\textcolor{green!50!black}{EN~LOCAL~EN~RTOS}\textcolor{black!48}{\pdftooltip[width=\textwidth]{.01}{Uczeń wyjaśnia nagłówek, wyrównanie, first-fit, split, adresową listę wolnych bloków i\textCR dwustronne coalescing.}}\par%
\hspace*{0.54em}\textcolor{blue!70!black}{KW~LOCAL~KW~RTOS}\textcolor{black!48}{\pdftooltip[width=\textwidth]{.01}{Łączy kod, diagram i zweryfikowany dowód.}}\par%
\end{minipage}%
}%
\end{minipage}%
}
}
\begin{document}
\sloppy
\vspace{1.0em}
\noindent{\Large\bfseries Cel karty}\par
\vspace{0.35em}
Uczeń przechodzi od liniowego kursora z K\&R 5.4 do wielokrotnego użycia tej samej areny: rozpoznaje nagłówek bloku, first-fit, split oraz dwustronne scalanie wolnych bloków w heap\_4.
\vspace{0.8em}
\noindent\textcolor{black!25}{\rule{\textwidth}{0.35pt}}
\vspace{0.7em}
\noindent{\Large\bfseries Zakres karty}\par
\vspace{0.35em}
Dwa małe modele C przygotowują przewidywanie. Główny replay uruchamia prawdziwe FreeRTOS-Kernel V11.3.0 heap\_4 na RV32I/Hazard3 i dowodzi fragmentacji, pełnego scalenia, minimum-ever oraz kontrolowanego OOM.
\vspace{0.55em}
\small\begin{tabularx}{\textwidth}{@{}>{\ttfamily\raggedright\arraybackslash}p{1.10cm}>{\ttfamily\raggedright\arraybackslash}p{1.45cm}X>{\raggedright\arraybackslash}p{2.50cm}>{\raggedright\arraybackslash}p{1.75cm}>{\ttfamily\raggedright\arraybackslash}p{1.50cm}@{}}
\textbf{Lekcja} & \textbf{Task} & \textbf{Najważniejsza idea} & \textbf{Priorytet} & \textbf{Status} & \textbf{Version} \\ \hline
\hline
\textbf{\texttt{FC01}} & \textbf{\texttt{Task01}} & \textbf{headers, address-ordered free list, first-fit, split, coalescing and heap statistics} & \textbf{główny} & \textbf{opracowane} & \textbf{\texttt{v00.01}} \\ \hline
\end{tabularx}
\normalsize
\vspace{0.8em}
\noindent\textcolor{black!25}{\rule{\textwidth}{0.35pt}}
\clearpage
\ESCSectionBlockStart
\noindent{\small\bfseries A1 — Od liniowego kursora do odzyskiwalnej areny \hfill część 1/1 \textperiodcentered\ r1 c1}\par
\vspace{0.35em}
\begin{figure}[H]
\centering
\includegraphics[width=0.47121\linewidth,trim=0.000bp 0.000bp 0.000bp 0.000bp,clip]{\detokenize{../assets/a1-context.png}}
\caption{A1 CONTEXT — od żądania aplikacji do rzeczywistych bajtów ucHeap. — część 1/1 (r1 c1).}
\label{fig:a1-context}
\end{figure}
\Needspace{6\baselineskip}
\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.35pt,colback=blue!2,colframe=blue!45!black,boxsep=0pt,left=1.2mm,right=1.2mm,top=0.7mm,bottom=0.7mm,colbacktitle=blue!7,coltitle=black,title={\ttfamily\bfseries INTERPRETACJA}]
Aplikacja korzysta z publicznego API, heap\_4 zarządza jedną areną, a Hazard3 pokazuje jej rzeczywisty stan.
\end{tcolorbox}
\ESCSectionBlockEnd
\clearpage
\ESCSectionBlockStart
\noindent{\small\bfseries A2 — Nagłówek, payload i lista wolnych bloków \hfill część 1/1 \textperiodcentered\ r1 c1}\par
\vspace{0.35em}
\begin{figure}[H]
\centering
\includegraphics[width=0.47273\linewidth,trim=0.000bp 0.000bp 0.000bp 0.000bp,clip]{\detokenize{../assets/a2-structure.png}}
\caption{A2 STRUCTURE — metadane wewnątrz areny i adresowo uporządkowana lista. — część 1/1 (r1 c1).}
\label{fig:a2-structure}
\end{figure}
\Needspace{6\baselineskip}
\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.35pt,colback=blue!2,colframe=blue!45!black,boxsep=0pt,left=1.2mm,right=1.2mm,top=0.7mm,bottom=0.7mm,colbacktitle=blue!7,coltitle=black,title={\ttfamily\bfseries INTERPRETACJA}]
Każdy blok ma nagłówek, a tylko wolne bloki wykorzystują wskaźnik next do budowy listy uporządkowanej adresami.
\end{tcolorbox}
\ESCSectionBlockEnd
\clearpage
\begin{landscape}
\ESCSectionBlockStart
\noindent{\small\bfseries A5 — First-fit, fragmentacja i pełne scalenie \hfill część 1/1 \textperiodcentered\ r1 c1}\par
\vspace{0.35em}
\begin{figure}[H]
\centering
\includegraphics[width=0.86383\linewidth,trim=0.000bp 0.000bp 0.000bp 0.000bp,clip]{\detokenize{../assets/a5-flow.png}}
\caption{A5 FLOW — inicjalizacja, A/B/C, fragmentacja, dwustronne scalenie i OOM. — część 1/1 (r1 c1).}
\label{fig:a5-flow}
\end{figure}
\Needspace{6\baselineskip}
\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.35pt,colback=blue!2,colframe=blue!45!black,boxsep=0pt,left=1.2mm,right=1.2mm,top=0.7mm,bottom=0.7mm,colbacktitle=blue!7,coltitle=black,title={\ttfamily\bfseries INTERPRETACJA}]
Jeden przebieg A/B/C przechodzi od pustej areny przez trzy przydziały i dwa wolne obszary do ponownie scalonego bloku.
\end{tcolorbox}
\ESCSectionBlockEnd
\end{landscape}
\clearpage
\ESCSectionBlockStart
\noindent{\small\bfseries A6 — Stan bloku a stan statystyk \hfill część 1/1 \textperiodcentered\ r1 c1}\par
\vspace{0.35em}
\begin{figure}[H]
\centering
\includegraphics[width=0.48636\linewidth,trim=0.000bp 0.000bp 0.000bp 0.000bp,clip]{\detokenize{../assets/a6-state.png}}
\caption{A6 STATE — wolny, przydzielony, rozdzielony, scalony oraz minimum-ever. — część 1/1 (r1 c1).}
\label{fig:a6-state}
\end{figure}
\Needspace{6\baselineskip}
\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.35pt,colback=blue!2,colframe=blue!45!black,boxsep=0pt,left=1.2mm,right=1.2mm,top=0.7mm,bottom=0.7mm,colbacktitle=blue!7,coltitle=black,title={\ttfamily\bfseries INTERPRETACJA}]
Bieżąca liczba wolnych bajtów może rosnąć po free, ale minimum-ever pozostaje historycznym minimum.
\end{tcolorbox}
\ESCSectionBlockEnd
\clearpage
\begin{landscape}
\ESCSectionBlockStart
\noindent{\small\bfseries A7 — Dowód w Hazard3 i ELF \hfill część 1/1 \textperiodcentered\ r1 c1}\par
\vspace{0.35em}
\begin{figure}[H]
\centering
\includegraphics[width=0.86596\linewidth,trim=0.000bp 0.000bp 0.000bp 0.000bp,clip]{\detokenize{../assets/a7-runtime.png}}
\caption{A7 RUNTIME — kod, ELF, checkpoint, pamięć i statystyki jednego przebiegu. — część 1/1 (r1 c1).}
\label{fig:a7-runtime}
\end{figure}
\Needspace{6\baselineskip}
\begin{tcolorbox}[enhanced,arc=0pt,boxrule=0.35pt,colback=blue!2,colframe=blue!45!black,boxsep=0pt,left=1.2mm,right=1.2mm,top=0.7mm,bottom=0.7mm,colbacktitle=blue!7,coltitle=black,title={\ttfamily\bfseries INTERPRETACJA}]
Ten sam artefakt łączy źródło, symbole ELF, osiem checkpointów, pamięć ucHeap i końcowe asercje.
\end{tcolorbox}
\ESCSectionBlockEnd
\end{landscape}
\clearpage
\ESCSectionBlockStart
\section{Task01 — mechanika heap\_4}
\begin{ESCTaskFrame}{TASK01 · Predict and prove reusable heap\_4 blocks}
{\scriptsize\ttfamily aea09ab7-9bfd-5368-8d1b-c8724871c1a7}\par
\begin{ESCBlockFrame}{A — przewidywanie}
Przejdź przez model nagłówka, split i porządek adresowy przed uruchomieniem prawdziwego heap\_4.
\begin{ESCStepFrame}{size · Policz rozmiary całych bloków.}
Rozróżnij surowy BlockLink\_t (8 bajtów) od xHeapStructSize (16 bajtów), dodaj nagłówek do żądań 24, 40 i 16 bajtów, a następnie wyrównaj wynik do 16.
\end{ESCStepFrame}
\begin{ESCStepFrame}{list · Narysuj listę po free(A,C).}
Zaznacz, dlaczego przydzielony B rozdziela dwa wolne obszary.
\end{ESCStepFrame}
\end{ESCBlockFrame}
\begin{ESCBlockFrame}{B — replay Hazard3}
Powiąż każdy stan diagramu z deterministycznym checkpointem E01--E08.
\begin{ESCStepFrame}{allocate · Sprawdź E01--E04.}
Potwierdź wartości 4080, 4032, 3968 i 3936 oraz zużycie 48/64/32 bajtów.
\end{ESCStepFrame}
\begin{ESCStepFrame}{release · Sprawdź E05--E07.}
Porównaj liczbę wolnych bloków i udowodnij scalenie poprzedniego, a potem następnego sąsiada.
\end{ESCStepFrame}
\begin{ESCStepFrame}{verify · Sprawdź E08.}
Udowodnij zachowanie minimum-ever, kontrolowany OOM, brak asercji i PASS=1.
\end{ESCStepFrame}
\end{ESCBlockFrame}
\begin{ESCBlockFrame}{Ćwiczenie · Ćwiczenie — ta sama suma, inna użyteczność}
Zaproponuj dwa układy wolnych bloków o tej samej sumie bajtów, ale tylko jeden zdolny obsłużyć wskazane duże żądanie. Uzasadnij odpowiedź przez largest-free-block.
\par\textbf{Evidence:} Dwa diagramy listy, suma wolnych bajtów, rozmiar największego bloku i wynik pvPortMalloc.
\par\textbf{Acceptance:} Uczeń nie utożsamia sumy wolnej pamięci z możliwością pojedynczego dużego przydziału.
\end{ESCBlockFrame}
\tcblower\textbf{Task acceptance:} Na RV32 BlockLink\_t ma 8 bajtów, lecz 16-bajtowe wyrównanie portu daje xHeapStructSize=16; A/B/C zużywają 48/64/32 bajty; po free(A,C) są dwa wolne bloki, po free(B) jeden; final free = initial free; minimum-ever nie rośnie; OOM zwraca NULL; PASS=1.
\end{ESCTaskFrame}
\begin{ESCConclusionFrame}
heap\_4 odzyskuje pamięć dzięki metadanym w arenie, adresowo uporządkowanej liście i scalaniu sąsiadów. Suma wolnych bajtów nie zastępuje informacji o największym bloku, a minimum-ever jest historią, nie bieżącym stanem.
\end{ESCConclusionFrame}
\ESCSectionBlockEnd
\end{document}
+102
View File
@@ -0,0 +1,102 @@
# FC01 — plan iteracji diagramów w Hazard3
## Zasada
Kursor porusza się po diagramie, nie po przypadkowych liniach programu.
Każda kotwica ma jeden z dwóch kontraktów:
- `CODE` — otwiera właściwe źródło lub dowód ELF; nie uruchamia programu;
- `RUN` — odtwarza program od czystego resetu do wskazanego checkpointu,
ustawia Neovima i udostępnia zestaw wyrażeń GDB.
Ten sam snapshot może wystąpić w kilku perspektywach. Nie powtarza to
eksperymentu: A2 pyta o strukturę, A6 o stan, a A7 o jakość dowodu.
## A1 CONTEXT — granice odpowiedzialności
| Step | Tryb | Otwórz | Pytanie kontrolne |
|---|---|---|---|
| 01 Application | CODE | `main()` | Czy aplikacja dotyka metadanych allocatora? |
| 02 FreeRTOS API | CODE | wywołania `pvPortMalloc`, `vPortFree`, stats | Gdzie kończy się publiczny kontrakt? |
| 03 heap_4 | CODE | upstream `heap_4.c` | Które funkcje wybierają, dzielą i scalają blok? |
| 04 ucHeap | CODE | definicja `ucHeap[4096]` | Gdzie fizycznie leżą nagłówki i payload? |
| 05 Hazard3 | CODE | test symboli ELF | Czy debugujemy dokładnie artefakt z karty? |
A1 nie ma checkpointu: opisuje architekturę, a nie zdarzenie runtime.
## A2 STRUCTURE — nagłówek, split i scalenie
| Step | Tryb / replay | Obserwuj | Warunek zaliczenia |
|---|---|---|---|
| 01 Header | CODE | `BlockLink_t`, `portBYTE_ALIGNMENT` | raw header=8 B, alignment=16 B, `xHeapStructSize`=16 B |
| 02 Alignment | RUN E02 | `g_a`, `g_a_consumed` | A jest wyrównane, cały blok zużywa 48 B |
| 03 Split | RUN E02 | `g_after_a_stats` | pozostaje 1 wolny blok i 4032 B |
| 04 Address order | RUN E06 | `g_a`, `g_b`, `g_c`, stats | adresy rosną, a B rozdziela 2 wolne obszary |
| 05 Merge previous | RUN E06 + step | `pxIterator`, `pxBlockToInsert` | poprzedni/lewy blok jest testowany i scalany pierwszy |
| 06 Merge next | RUN E06 + step | powiększony blok i `pxNextFreeBlock` | następny/prawy blok jest scalany drugi |
Dla kroków 0506 po replay E06:
```gdb
tbreak prvInsertBlockIntoFreeList
continue # wykonaj vPortFree(g_b)
p pxIterator
p pxBlockToInsert
next # test poprzedniego/lewego sąsiada
next # test następnego/prawego sąsiada
```
## A5 FLOW — pełny przebieg
| Event | Operacja | Wartości RV32/Hazard3 | Dowód |
|---|---|---|---|
| E01 | reset/init | free=4080 | 1 blok, largest=4080 |
| E02 | alloc A(24) | consumed=48, free=4032 | A != NULL, aligned=1 |
| E03 | alloc B(40) | consumed=64, free=3968 | B != NULL, aligned=1 |
| E04 | alloc C(16) | consumed=32, free=3936 | C != NULL, aligned=1 |
| E05 | free A | free=3984 | 2 wolne bloki |
| E06 | free C | free=4016 | 2 bloki, free > largest |
| E07 | free B | free=largest=4080 | 1 wolny blok, minimum-ever=3936 |
| E08 | oversized alloc | NULL | hook=1, asserts=0, layout=1, PASS=1 |
Każdy Enter na A5 wykonuje czysty replay do dokładnie jednego eventu. Nie
kontynuujemy stanu pozostałego po poprzednim kroku.
## A6 STATE — znaczenie liczników
| Step | Replay | Hipoteza |
|---|---|---|
| 01 Free | E01 | current free i largest są równe |
| 02 Allocated | E04 | przydziały zmniejszają current free do 3936 |
| 03 Fragmented | E06 | total free może być większe od largest |
| 04 Coalesced | E07 | current, largest i initial znów są równe |
| 05 Minimum-ever | E08 | minimum-ever pozostaje 3936 mimo odzyskania areny |
## A7 RUNTIME — jakość dowodu
| Step | Tryb / replay | Co musi znaleźć się w dowodzie |
|---|---|---|
| 01 Source | CODE | blob źródła eksperymentu |
| 02 ELF | CODE | SHA artefaktu i symbole upstream/checkpointów |
| 03 Fragmented | RUN E06 | PC, 2 bloki, free=4016, largest<free |
| 04 Memory | RUN E06 | adres `ucHeap`, adresy A/B/C i bajty nagłówków |
| 05 Verdict | RUN E08 | final=initial, OOM NULL, hook=1, asserts=0, PASS=1 |
Snapshot do raportu jest kompletny dopiero wtedy, gdy łączy nazwę eventu,
tożsamość ELF, pozycję programu i wartości rozstrzygające hipotezę.
## Świadomie pominięte perspektywy
- A3 DISPATCH — allocator nie ma callbacku ani mechanizmu dispatch;
- A4 APPLICATION — konkretny eksperyment A/B/C jest pełnym A5;
- A8 PATTERNS — first-fit i intrusive address-ordered list są już mierzalne w
A2 i A5; osobny diagram powielałby materiał.
## Definition of done
1. Hostowe modele i adapter przechodzą `tests/test_host.sh`.
2. ELF RV32 zawiera upstream `heap_4` oraz osiem symboli checkpointów.
3. Hazard3 RTL kończy Task03 kodem `0`.
4. E01E08 spełniają wyrażenia z `debug_checkpoints`.
5. Wszystkie kroki RUN mają `snapshot_ref`; kroki CODE nie udają runtime.
6. SVG, HTML i TeX powstają z tego samego `json/card_source.json`.
+280 -224
View File
@@ -1,21 +1,19 @@
\documentclass[12pt]{article}
\documentclass[10pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[polish]{babel}
\usepackage[a4paper,margin=2.0cm]{geometry}
\usepackage{array}
\usepackage{tabularx}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{hyperref}
\usepackage{fancyhdr}
\usepackage{lastpage}
\usepackage[a4paper,margin=1.55cm]{geometry}
\usepackage{array,tabularx,booktabs}
\usepackage{amsmath,amssymb}
\usepackage{xcolor,listings}
\usepackage{hyperref,fancyhdr,lastpage}
\usepackage{enumitem}
\definecolor{accent}{HTML}{16324A}
\definecolor{accentlight}{HTML}{EEF3F7}
\definecolor{rulegray}{HTML}{D7DEE5}
\hypersetup{colorlinks=true,linkcolor=blue,urlcolor=blue,citecolor=blue}
\definecolor{success}{HTML}{236B45}
\hypersetup{colorlinks=true,linkcolor=accent,urlcolor=blue}
\IfFileExists{build-meta.tex}{\input{build-meta.tex}}{\newcommand{\BuildCommit}{local}}
\newcommand{\PublisherDomain}{mpabi}
\newcommand{\DocumentAuthor}{M. Pabiszczak}
@@ -23,236 +21,294 @@
\newcommand{\CardArea}{inf}
\newcommand{\CardSeries}{rv32i-freertos}
\newcommand{\CardNumber}{01}
\newcommand{\CardCount}{??}
\newcommand{\CardCount}{15}
\newcommand{\CardSlug}{heap4}
\newcommand{\CardVersion}{v0.1}
\newcommand{\CardVersion}{v0.3}
\newcommand{\DocumentKey}{\PublisherDomain/\CardArea/\CardSeries/\CardNumber/\CardSlug/\CardVersion}
\newcommand{\DocumentUUID}{4654524c-73f2-46df-83a3-d448ba6d6c5a}
\renewcommand{\lstlistingname}{Listing}
\renewcommand{\lstlistlistingname}{Lista listingów}
\lstset{basicstyle=\ttfamily\small,columns=fullflexible,keepspaces=true,frame=single,breaklines=true,showstringspaces=false,numbers=left,numberstyle=\tiny\color{accent},stepnumber=1,numbersep=8pt,backgroundcolor=\color{accentlight},rulecolor=\color{rulegray},captionpos=b}
\newcommand{\TaskSection}[5]{\section{Task #1: #3}\subsection*{Algorytm i zakresy linii}#4\lstinputlisting[language=C,caption={Task #1: #3},label={lst:task#1-c}]{../src/tasks/#2.c}\subsection*{Co sprawdzić w ASM}#5\lstinputlisting[basicstyle=\ttfamily\scriptsize,caption={ASM dla task #1},label={lst:task#1-asm}]{../build/#2/#2.s}}
\lstset{
language=C,basicstyle=\ttfamily\scriptsize,columns=fullflexible,
keepspaces=true,frame=single,breaklines=true,showstringspaces=false,
numbers=none,backgroundcolor=\color{accentlight},rulecolor=\color{rulegray}
}
\pagestyle{fancy}
\fancyhf{}
\lhead{\textbf{FreeRTOS: heap\_4}}
\rhead{\small \DocumentAuthor, \DocumentYear}
\lhead{\textbf{FC01 · FreeRTOS \texttt{heap\_4}}}
\rhead{\small 30 minut · Pico 2 W / RP2350}
\lfoot{\scriptsize commit \BuildCommit}
\cfoot{\scriptsize \thepage/\pageref{LastPage}}
\rfoot{\scriptsize uuid \DocumentUUID}
\renewcommand{\headrulewidth}{0.4pt}
\setlength{\headheight}{18pt}
\setlength{\footskip}{24pt}
\rfoot{\scriptsize V11.3.0 / \CardVersion}
\setlength{\headheight}{14pt}
\setlength{\footskip}{19pt}
\setlist[itemize]{nosep,leftmargin=1.45em}
\setlist[enumerate]{nosep,leftmargin=1.65em}
\newcommand{\checkline}{\(\square\)\;}
\newcommand{\blank}[1]{\rule{#1}{.2pt}}
\begin{document}
\sloppy
\noindent
\begin{tabular}{@{}lp{0.72\textwidth}@{}}
Project: & FreeRTOS: \texttt{heap\_4} \\
Subject: & Informatyka \\
Level: & 1, Zakres Podstawowy, PP \\
Topic: & dynamiczna alokacja pamięci, lista wolnych bloków, scalanie bloków \\
Revision date: & 02.05.2026 \\
Status: & Draft \\
Card in series: & \small\texttt{\CardNumber/\CardCount} \\
Card version: & \small\texttt{\CardVersion} \\
Card key: & \small\texttt{\DocumentKey} \\
UUID: & \small\texttt{\DocumentUUID} \\
Commit: & \small\texttt{\BuildCommit} \\
Scope: & pierwsza karta serii FreeRTOS; model dydaktyczny mechaniki \texttt{heap\_4.c} \\
Files used: & \small
\begin{tabular}[t]{@{}l@{}}
Task01: \texttt{task01\_heap\_map.c} \\
Task02: \texttt{task02\_free\_list.c} \\
Task03: \texttt{task03\_heap\_init.c} \\
Task04: \texttt{task04\_alignment.c} \\
Task05: \texttt{task05\_malloc\_first\_fit.c} \\
Task06: \texttt{task06\_split\_block.c} \\
Task07: \texttt{task07\_free\_insert.c} \\
Task08: \texttt{task08\_coalescing.c} \\
Task09: \texttt{task09\_config\_macros.c} \\
Task10: \texttt{task10\_heap4\_demo.c} \\
Common: \texttt{heap4\_common.h} \\
Runtime: \texttt{memops.c} \\
Startup: \texttt{crt0.S}
\end{tabular}
\end{tabular}
\vspace{0.8em}
\noindent\rule{\textwidth}{0.5pt}
\begin{center}
{\LARGE\bfseries FreeRTOS \texttt{heap\_4}: od kursora do wolnych bloków}\par
\vspace{.25em}
{\large bezpośrednia kontynuacja projektu K\&R 5.4}\par
\end{center}
\section{Cel}
Ta karta zaczyna serię FreeRTOS od \texttt{heap\_4}, ponieważ ten plik jest
naturalnym pomostem po kartach z języka C. Wymaga wskaźników, tablic,
struktur, listy jednokierunkowej, \texttt{static}, \texttt{typedef}, makr oraz
arytmetyki adresów, ale nie wymaga jeszcze schedulera, przerwań ani
uruchamiania tasków.
Przykłady są małym modelem edukacyjnym mechaniki \texttt{heap\_4.c}. Nie są
kopią pliku upstream FreeRTOS. Na RV32I wyniki są zapisywane w globalnych
zmiennych \texttt{volatile}; \texttt{printf} jest dostępny wyłącznie w wariancie
hostowym przez flagę \texttt{-DHOST\_PRINTF=1}.
Listingi C i ASM mają numerowane linie. Opisy w sekcjach tasków odnoszą się
do numerów widocznych po lewej stronie listingów C.
\lstinputlisting[language=C,caption={Wspólny nagłówek dla karty \texttt{heap\_4}},label={lst:common-h}]{../src/tasks/heap4_common.h}
\subsection{\texttt{static inline} w nagłówku}
Helpery z Listingu~\ref{lst:common-h} są zapisane jako \texttt{static inline},
bo każdy task jest osobnym programem i dołącza ten sam nagłówek. \texttt{static}
daje prywatną kopię funkcji w każdym pliku \texttt{.c}, a \texttt{inline}
pozwala kompilatorowi wstawić krótkie obliczenia, takie jak wyrównanie rozmiaru
lub sprawdzenie bitu alokacji, bez kosztu zwykłego wywołania funkcji.
\section{Mapa karty}
\begin{tabularx}{\textwidth}{|p{2.1cm}|X|}
\hline
Task & Temat \\
\hline
1 & Mapa pojęć: obszar sterty, nagłówek bloku i bit alokacji. \\
\hline
2 & Lista wolnych bloków jako lista jednokierunkowa. \\
\hline
3 & Inicjalizacja sterty, pierwszy wolny blok i wartownik końca listy. \\
\hline
4 & Wyrównanie rozmiarów żądań i adresu początku sterty. \\
\hline
5 & Pierwszy pasujący blok, czyli zasada \texttt{first fit}. \\
\hline
6 & Podział dużego bloku na część przydzieloną i pozostały blok wolny. \\
\hline
7 & Zwracanie bloku i wstawianie go do listy według adresu. \\
\hline
8 & Scalanie sąsiednich wolnych bloków. \\
\hline
9 & Makra konfiguracyjne oraz hostowy \texttt{TRACE\_PRINTF}. \\
\hline
10 & Mini-demonstracja sekwencji \texttt{malloc/free}. \\
\hline
\noindent\begin{tabularx}{\textwidth}{@{}p{1.45cm}Xp{1.4cm}X@{}}
\toprule
Karta & FC01 / \CardCount & Czas & 30 minut \\
Płytka & Raspberry Pi Pico 2 W & Układ & RP2350, rdzeń RISC-V \\
Allocator & FreeRTOS-Kernel V11.3.0 & Źródło & upstream \texttt{heap\_4.c} \\
Wersja & \CardVersion & Data & 19.07.2026 \\
\bottomrule
\end{tabularx}
\TaskSection{01}{task01_heap_map}{mapa \texttt{heap\_4}}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 3--7 definiują zmienne \texttt{volatile}, czyli obserwowalne wyniki taska.
\item Linie 11--16 tworzą pojedynczy blok i zapisują w jego polu \texttt{size} rozmiar z bitem alokacji.
\item Linie 18--22 rozbijają nagłówek bloku na wartości pomocnicze: rozmiar nagłówka, rozmiar wyrównany, bit zajętości, rozmiar całego bloku i część użytkownika.
\item Linie 24--27 wypisują te same wartości tylko w wariancie hostowym; na RV32I makro \texttt{TRACE\_PRINTF} znika.
\item Wynik sprawdzaj w \texttt{g\_header\_size}, \texttt{g\_allocated\_bit\_set}, \texttt{g\_total\_block\_bytes} i \texttt{g\_user\_bytes}.
\end{itemize}
}{
W ASM szukaj operacji ustawiania najwyższego bitu rozmiaru oraz zapisów do symboli globalnych \texttt{g\_*}. Dostęp do pól \texttt{block.next} i \texttt{block.size} powinien być zwykłym zapisem pod adres bazowy stosu z przesunięciem.
}
\TaskSection{02}{task02_free_list}{lista wolnych bloków}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 7--16 implementują sumowanie rozmiarów bloków na liście.
\item Linie 18--28 przechodzą po tej samej liście i zapamiętują największy blok.
\item Linie 30--39 liczą liczbę węzłów listy.
\item Linie 43--55 budują ręcznie listę \texttt{start -> a -> b -> c -> NULL}.
\item Linie 57--59 uruchamiają trzy funkcje pomiarowe i zapisują wyniki w \texttt{volatile}.
\end{itemize}
}{
W ASM zwróć uwagę na pętle po wskaźniku \texttt{block = block->next}. To jest podstawowy idiom przechodzenia po liście jednokierunkowej, widoczny jako ładowanie pola \texttt{next} i skok warunkowy.
}
\TaskSection{03}{task03_heap_init}{inicjalizacja sterty}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 3--7 definiują bufor sterty, węzeł startowy listy i wskaźnik końcowego wartownika.
\item Linie 20--23 wyrównują początek sterty i obcinają dostępną długość do wielokrotności wyrównania.
\item Linie 25--28 ustawiają adres i pola końcowego wartownika.
\item Linie 30--34 tworzą pierwszy wolny blok i podpinają go za \texttt{start}.
\item Linie 39--43 wykonują inicjalizację i zapisują trzy wartości kontrolne.
\end{itemize}
}{
W ASM szukaj maskowania dolnych bitów adresu i rozmiaru. Warto też porównać zapisy do \texttt{first->next}, \texttt{first->size}, \texttt{start.next} i \texttt{start.size}; każdy z nich jest dostępem do pola struktury.
}
\TaskSection{04}{task04_alignment}{wyrównanie}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 3--6 definiują wyniki pokazujące wpływ wyrównania.
\item Linie 14--16 liczą rzeczywiste rozmiary bloków dla żądań 1, 9 i 17 bajtów, po dodaniu nagłówka.
\item Linie 18--20 biorą celowo nie-wyrównany adres \texttt{\&bytes[1]} i wyliczają przesunięcie do kolejnej granicy wyrównania.
\item Linie 22--24 są hostowym wypisem kontrolnym.
\end{itemize}
}{
W ASM znajdź operacje \texttt{and} używane do testowania dolnych bitów oraz dodawanie brakującej liczby bajtów do wyrównania. To jest ten sam mechanizm, którego używa alokator dla rozmiaru bloku i początku sterty.
}
\TaskSection{05}{task05_malloc_first_fit}{\texttt{first fit}}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 13--30 inicjalizują stertę z jednym wolnym blokiem oraz wartownikiem końca.
\item Linie 38--40 zamieniają żądanie użytkownika na całkowity rozmiar bloku i ustawiają początek przeszukiwania listy.
\item Linie 42--51 realizują algorytm \texttt{first fit}: idą po liście do pierwszego bloku o wystarczającym rozmiarze.
\item Linie 44--47 zdejmują znaleziony blok z listy wolnych, oznaczają go jako zajęty i zwracają adres danych użytkownika.
\item Linie 61--67 wykonują alokację i zapisują, czy się udała, jaki rozmiar dostał blok i ile wolnego miejsca zostało na liście.
\end{itemize}
}{
W ASM obserwuj porównanie \texttt{block->size >= total}, zmianę \texttt{previous->next} oraz dodanie \texttt{sizeof(HeapBlock)} do adresu bloku przed zwróceniem wskaźnika użytkownika.
}
\TaskSection{06}{task06_split_block}{podział bloku}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 3--12 definiują rozmiar sterty, minimalny sensowny rozmiar reszty i zmienne wynikowe.
\item Linie 14--28 tworzą jeden duży wolny blok.
\item Linie 38--44 szukają bloku pasującego do żądania i zapamiętują jego pierwotny rozmiar.
\item Linie 45--50 wykonują podział: nowy blok \texttt{remainder} zaczyna się pod adresem \texttt{block + total}.
\item Linie 51--56 obsługują przypadek bez podziału, oznaczają blok jako zajęty i zwracają adres użytkownika.
\item Linie 65--73 liczą pozostałe wolne bloki, a linie 81--87 zapisują wynik demonstracji.
\end{itemize}
}{
W ASM szukaj arytmetyki adresów dla \texttt{remainder}: adres bloku plus \texttt{total}. To najważniejszy fragment pokazujący, że dzielenie bloku jest tylko przesunięciem wskaźnika i zapisaniem nowego nagłówka.
}
\TaskSection{07}{task07_free_insert}{\texttt{free} i wstawianie}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 11--20 wstawiają blok do listy w miejscu wynikającym z porządku adresów.
\item Linie 22--32 modelują \texttt{free}: z adresu użytkownika wracają do nagłówka bloku, czyszczą bit alokacji i wywołują wstawianie.
\item Linie 34--54 zawierają funkcje kontrolne liczące węzły oraz łączny rozmiar wolnej pamięci.
\item Linie 63--76 budują układ \texttt{a}, \texttt{b}, \texttt{c}, gdzie \texttt{b} jest zajętym blokiem między dwoma wolnymi.
\item Linie 78--83 zwalniają \texttt{b} i sprawdzają, czy lista ma kolejność \texttt{a -> b -> c -> end}.
\end{itemize}
}{
W ASM zwróć uwagę na porównywanie adresów w pętli z linii 15. To porządkowanie po adresie jest przygotowaniem do scalania bloków w następnym tasku.
}
\TaskSection{08}{task08_coalescing}{scalanie bloków}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 11--17 znajdują miejsce w liście, w którym powinien znaleźć się zwracany blok.
\item Linie 19--25 sprawdzają sąsiedztwo z prawym blokiem; jeśli adres końca zwracanego bloku jest adresem następnego, rozmiary są łączone.
\item Linie 27--32 sprawdzają sąsiedztwo z lewym blokiem i ewentualnie dołączają scalony wynik do lewej strony.
\item Linie 35--44 liczą końcową liczbę wolnych bloków.
\item Linie 52--65 budują trzy sąsiednie bloki w pamięci, a linia 67 uruchamia scalanie środkowego bloku.
\item Linie 69--71 zapisują, czy po scaleniu został jeden blok i jaki ma rozmiar.
\end{itemize}
}{
W ASM szukaj testu \texttt{(uint8\_t *)block + block->size == iterator->next}. To jest sedno scalania: alokator nie porównuje indeksów, tylko rzeczywiste adresy końca i początku bloków.
}
\TaskSection{09}{task09_config_macros}{makra konfiguracyjne}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 3--9 definiują wartości domyślne tylko wtedy, gdy nie zostały podane z zewnątrz przez kompilator.
\item Linia 11 tworzy wartość pochodną od konfiguracji i wyrównania.
\item Linie 20--22 zapisują wartości makr do zmiennych \texttt{volatile}, żeby były widoczne w debugerze.
\item Linie 24--28 pokazują kompilację warunkową: host ustawia \texttt{g\_trace\_is\_host\_only} na 1, RV32I na 0.
\item Linie 30--32 wypisują wynik tylko w wariancie hostowym.
\end{itemize}
}{
W ASM dla RV32I nie powinno być wywołania \texttt{printf}. Sprawdź też, że makra konfiguracyjne nie są zmiennymi w pamięci, tylko stałymi wstawionymi do kodu przez preprocesor.
}
\TaskSection{10}{task10_heap4_demo}{mini \texttt{heap\_4}}{
\begin{itemize}[leftmargin=1.6em]
\item Linie 18--38 to funkcje diagnostyczne przechodzące po liście wolnych bloków.
\item Linie 40--62 wstawiają blok i scalają go z prawym oraz lewym sąsiadem.
\item Linie 64--88 inicjalizują stertę: wyrównują początek, ustawiają wartownika, pierwszy wolny blok i liczniki wolnej pamięci.
\item Linie 90--131 implementują alokację: sprawdzają rozmiar żądania, szukają bloku, dzielą go lub zdejmują w całości z listy, oznaczają jako zajęty i aktualizują minimum wolnej pamięci.
\item Linie 133--149 implementują zwalnianie: wracają z adresu użytkownika do nagłówka, sprawdzają bit alokacji, przywracają rozmiar i scalają blok.
\item Linie 157--169 wykonują sekwencję \texttt{malloc/free} i zapisują stan końcowy alokatora.
\end{itemize}
}{
W ASM porównaj trzy fragmenty: inicjalizację listy, pętlę szukania wolnego bloku oraz wywołanie \texttt{insert\_block\_merge}. To pokazuje, że pełny model składa się z prostych operacji wskaźnikowych poznanych w poprzednich taskach.
}
\section*{Punkt startowy — tego już nie powtarzamy}
\section{Polecenia}
\begin{enumerate}[leftmargin=1.6em]
\item Zbuduj kartę dla RV32I poleceniem \texttt{make tasks}.
\item Zbuduj wariant hostowy poleceniem \texttt{make host}; wypisywanie działa tylko przez \texttt{HOST\_PRINTF}.
\item W tasku 6 zmień próg \texttt{MIN\_SPLIT\_SIZE} i sprawdź, kiedy blok nie jest dzielony.
\item W tasku 8 zmień rozmiary bloków tak, aby scalanie działało tylko z prawym sąsiadem.
\item W tasku 10 dodaj większą alokację, która ma się nie udać, i zapisz status w nowej zmiennej \texttt{volatile}.
Z poprzedniej karty działa projekt:
\begin{lstlisting}
allocbuf[64]; allocp = allocbuf;
alloc_local(5) -> offset 0
alloc_local(7) -> offset 5
allocp -> offset 12
alloc_local(0) i OOM -> NULL; kursor pozostaje na 12
\end{lstlisting}
\noindent\fcolorbox{accent}{accentlight}{%
\begin{minipage}{.94\textwidth}
\textbf{Pytanie projektowe.} Jak zwolnić obszar 5 B spod offsetu 0, zachować
późniejszy obszar 7 B spod offsetu 5 i ponownie wykorzystać powstałą dziurę?
W naszym projekcie nie istnieje \texttt{free}; reset odzyskuje całą arenę.
Samo cofnięcie kursora zniszczyłoby również późniejsze przydziały.
\end{minipage}}
\section*{Cel lekcji}
Potrafię wskazać trzy elementy dodane przez \texttt{heap\_4} do alokatora
liniowego --- \textbf{nagłówek bloku, listę wolnych bloków i scalanie} --- oraz
potwierdzić ich działanie na prawdziwym \texttt{heap\_4.c}.
\section*{Plan 30 minut}
\begin{tabularx}{\textwidth}{@{}p{1.55cm}p{3.0cm}X@{}}
\toprule
Czas & Tryb & Wynik \\
\midrule
0--3 & problem K\&R & nazwać, dlaczego jeden kursor nie zwolni obszaru ze środka \\
3--4 & kontekst & FreeRTOS linkuje jedną implementację; tutaj pracujemy tylko z \texttt{heap\_4} \\
4--9 & Demo 1 & przewidzieć nagłówek, first-fit i split \\
9--16 & Demo 2 & przewidzieć listę adresową i scalenie \texttt{2 -> 1} \\
16--27 & Task 3 RUN & osiem checkpointów E01--E08 prawdziwego \texttt{heap\_4.c} \\
27--30 & wyjście & odróżnić total free, largest free i minimum-ever \\
\bottomrule
\end{tabularx}
\vfill
\noindent\textbf{Jedna minuta kontekstu:} \texttt{heap\_1} przypomina rosnący
kursor bez \texttt{free}; \texttt{heap\_2} nie scala; \texttt{heap\_3} używa
alokatora biblioteki C; \texttt{heap\_5} rozszerza mechanikę \texttt{heap\_4}
na wiele regionów. Nie są to tematy tej lekcji.
\newpage
\section{Most: od K\&R 5.4 do \texttt{heap\_4}}
\begin{tabularx}{\textwidth}{@{}p{3.5cm}p{4.8cm}X@{}}
\toprule
K\&R 5.4 — co mamy & Ograniczenie & Co dodaje \texttt{heap\_4} \\
\midrule
\texttt{allocbuf[64]}, \texttt{allocp} & istnieje tylko wolny ogon areny & arena podzielona na opisane bloki \\
wynik to surowy adres & później nie znamy rozmiaru obszaru & nagłówek \texttt{BlockLink\_t} przed payloadem \\
przydział przesuwa kursor & nie wykorzystamy dziury & lista wolnych bloków i first-fit \\
reset całej areny & brak zwolnienia jednego obszaru & \texttt{vPortFree()} wskazanego bloku \\
brak relacji między dziurami & sąsiednie dziury są rozdzielone & porządek adresowy i coalescing \\
sukces albo \texttt{NULL} & brak miary fragmentacji & free, largest, block count, minimum-ever \\
\bottomrule
\end{tabularx}
\subsection*{Nagłówek realnego bloku}
\begin{lstlisting}
typedef struct A_BLOCK_LINK {
struct A_BLOCK_LINK *pxNextFreeBlock;
size_t xBlockSize; /* MSB oznacza blok przydzielony */
} BlockLink_t;
[ BlockLink_t | payload zwracany przez pvPortMalloc() ]
^ metadata ^ adres widziany przez aplikacje
\end{lstlisting}
\textbf{Granica modelu:} Task 1--2 używają uproszczonego nagłówka
\texttt{\{next,size\}}. Bit allocated i pełne zabezpieczenia oglądamy dopiero
w upstream \texttt{heap\_4.c}.
\section{Demo 1 — pierwszy pasujący blok i split (5 minut)}
Na RP2350/RV32 nagłówek modelu ma 8 B. Dla żądania 13 B:
\[
\texttt{wanted}=\operatorname{align8}(8+13)=24\ \mathrm{B}
\]
\begin{lstlisting}
free list przed: [ block 16 B ] -> [ block 256 B ] -> END
request po naglowku i align8: 24 B
\end{lstlisting}
\textbf{Predykcja — wpisz przed odsłonięciem:}
\begin{enumerate}
\item Pierwszy pasujący blok ma \blank{1.5cm} B.
\item Blok przydzielony ma \blank{1.5cm} B, a remainder \blank{1.5cm} B.
\item Równość zachowania areny: \blank{2cm} + \blank{2cm} = 256 B.
\end{enumerate}
\noindent\textbf{Sprawdzenie po predykcji:}
\texttt{16 B} nie mieści żądania, więc first-fit wybiera \texttt{256 B}; split
daje \texttt{24 B + 232 B}. Realny \texttt{heap\_4} dzieli blok tylko wtedy,
gdy reszta jest większa od minimalnego rozmiaru bloku.
\noindent\textbf{Nie uruchamiamy osobnego debugowania Task 1.} Model służy do
policzenia geometrii; centralny RUN jest w Task 3.
\newpage
\section{Demo 2 — lista adresowa i coalescing (7 minut)}
\begin{center}
\texttt{[ A:48 FREE ][ B:48 USED ][ C:48 FREE ]}
\end{center}
\begin{lstlisting}
pamiec: A -------- B -------- C
free list: A ------------------> C -> END
\end{lstlisting}
\textbf{Predykcja:} po \texttt{vPortFree(B)} narysuj listę i uzupełnij:
\begin{tabular}{@{}lccc@{}}
\toprule
Stan & liczba wolnych bloków & suma wolna & największy blok \\
\midrule
przed zwolnieniem B & \blank{1.2cm} & \blank{1.2cm} & \blank{1.2cm} \\
po zwolnieniu B & \blank{1.2cm} & \blank{1.2cm} & \blank{1.2cm} \\
\bottomrule
\end{tabular}
\subsection*{Odsłoń po zapisaniu predykcji}
\begin{enumerate}
\item Wstaw B między A i C według adresu.
\item \texttt{end(B) == address(C)}: połącz B z C.
\item \texttt{end(A) == address(BC)}: połącz A z BC.
\end{enumerate}
\begin{lstlisting}
przed: A:48 -> C:48 -> END blocks=2 total=96 largest=48
po: A:144 -> END blocks=1 total=144 largest=144
\end{lstlisting}
Porządek po adresie sprawia, że fizycznych sąsiadów można sprawdzić podczas
jednego wstawienia. Uproszczony Task 2 scala prawą, a następnie lewą stronę.
Właściwy \texttt{prvInsertBlockIntoFreeList()} z FreeRTOS V11.3.0 wykonuje
te same dwa testy w kolejności: poprzedni/lewy, następnie kolejny/prawy blok.
\section{Task 3 — jedyny centralny RUN (11 minut)}
Obraz i sesja muszą być przygotowane przed lekcją. Nie kompilujemy ani nie
flashujemy w czasie tych 30 minut.
\begin{lstlisting}[language=bash]
# wykonane przed lekcja:
stemctl debug rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
\end{lstlisting}
\begin{lstlisting}
RESET/INIT
-> heap4_reset_checkpoint # E01: free=4080
-> heap4_alloc_a_checkpoint # E02: free=4032, used=48
-> heap4_alloc_b_checkpoint # E03: free=3968, used=64
-> heap4_alloc_c_checkpoint # E04: free=3936, used=32
-> heap4_free_a_checkpoint # E05: free=3984, blocks=2
-> heap4_fragmented_checkpoint # E06: free=4016, blocks=2
-> heap4_coalesced_checkpoint # E07: free=4080, blocks=1
-> task03_debug_checkpoint # E08: OOM, hook, PASS
\end{lstlisting}
\textbf{E01--E04:} sprawdź, że zużycie obejmuje wyrównany nagłówek całego
bloku, a nie tylko payload. \textbf{E05--E06:} porównaj sumę wolną z largest.
Przed przejściem z E06 do E07 ustaw tymczasowy breakpoint na
\texttt{prvInsertBlockIntoFreeList()} i sprawdź oba testy sąsiedztwa.
\textbf{E07--E08:} potwierdź odzyskanie areny, minimum-ever, OOM i hook.
\newpage
\section{Dowód na Pico 2 W / RP2350}
\textbf{Ważne:} \texttt{heap\_4} jest plikiem wybranym i linkowanym przez
projekt. Nie jest sprzętowym heapem ani peryferium RP2350. Pico 2 W dostarcza
realną pamięć SRAM, w której obserwujemy ten sam algorytm.
\subsection*{Minimalny widok GDB}
\begin{lstlisting}
p g_fragmented_stats
p g_final_stats
p g_a_consumed
p g_b_consumed
p g_c_consumed
p xFreeBytesRemaining
p xMinimumEverFreeBytesRemaining
p xStart
p pxEnd
x/160bx ucHeap
\end{lstlisting}
\subsection*{Tabela obserwacji}
\begin{tabularx}{\textwidth}{@{}p{4.2cm}p{3.0cm}X@{}}
\toprule
Wielkość & Odczyt & Warunek \\
\midrule
\texttt{initial\_free} & \blank{2.3cm} & punkt odniesienia \\
\texttt{after\_allocations} & \blank{2.3cm} & mniejsze niż initial \\
E06: free blocks & \blank{2.3cm} & równe 2 \\
E06: total / largest & \blank{2.3cm} & largest mniejsze niż total \\
E07: final free & \blank{2.3cm} & równe initial \\
E07: free blocks & \blank{2.3cm} & równe 1 \\
minimum-ever & \blank{2.3cm} & nie rośnie po free \\
OOM / hook / asserts / pass & \blank{2.3cm} & \texttt{1 / 1 / 0 / 1} \\
\bottomrule
\end{tabularx}
\section*{Wyjście — trzy minuty}
\begin{enumerate}
\item Dlaczego jeden \texttt{allocp} nie wystarcza do zwolnienia obszaru
spod offsetu 0 przy zachowaniu obszaru spod offsetu 5?\\[.35em]
\blank{.96\linewidth}
\item Jak \texttt{vPortFree()} znajduje rozmiar payloadu, skoro dostaje tylko
jego adres?\\[.35em]
\blank{.96\linewidth}
\item Dlaczego 96 wolnych bajtów w dwóch blokach nie pozwala przydzielić
jednego bloku 80 B?\\[.35em]
\blank{.96\linewidth}
\end{enumerate}
\subsection*{Zaliczenie}
\begin{itemize}
\item \checkline wymieniam: header, free list, coalescing;
\item \checkline przewiduję \texttt{2 bloki -> 1 blok};
\item \checkline odróżniam payload, metadata allocatora i stos \texttt{sp};
\item \checkline odróżniam current free, largest free i minimum-ever;
\item \checkline Task 3 kończy się
\texttt{aligned=1 oom=1 hooks=1 asserts=0 pass=1}.
\end{itemize}
\vfill
\noindent\textbf{Poza lekcją:} pełne czytanie upstream \texttt{heap\_4.c},
osobne uruchomienie Task 1--2 na AMD64/Hazard3, samodzielny deploy RP2350 oraz
porównanie z \texttt{heap\_1}, \texttt{heap\_2}, \texttt{heap\_3} i
\texttt{heap\_5}.
\end{document}
+1 -1
View File
@@ -1 +1 @@
e69aaa6d61af39003186415f3581d519e7a290bd
48eccb5e2497b692892c7b24ffa1ed7a6f8480b8
+51
View File
@@ -0,0 +1,51 @@
# FC01 `heap_4` — stan weryfikacji
## Stan na 2026-07-20
Karta ma jeden centralny eksperyment na niezmodyfikowanym
`heap_4.c` z FreeRTOS-Kernel V11.3.0. Przebieg jest podzielony na osiem
deterministycznych checkpointów E01E08 i działa na RV32I/Hazard3.
## Potwierdzone na Hazard3
| Event | Stan | Dowód |
|---|---|---|
| E01 | arena po inicjalizacji | `free=largest=4080`, 1 blok |
| E02 | `alloc A(24)` | zużyto 48, zostało 4032 |
| E03 | `alloc B(40)` | zużyto 64, zostało 3968 |
| E04 | `alloc C(16)` | zużyto 32, zostało 3936 |
| E05 | `free(A)` | 3984, 2 wolne bloki |
| E06 | `free(C)` | 4016, 2 bloki, `free > largest` |
| E07 | `free(B)` | `free=largest=4080`, 1 blok |
| E08 | kontrolowany OOM | `NULL`, hook=1, asserts=0, PASS=1 |
Na RV32 `sizeof(BlockLink_t) == 8`, ale `portBYTE_ALIGNMENT == 16`, więc
prywatne `xHeapStructSize == 16`. To wyjaśnia zużycie 48/64/32 bajtów.
## Diagramy i iteracja
- A1 CONTEXT: pięć kroków CODE — granice odpowiedzialności.
- A2 STRUCTURE: jeden krok CODE i pięć kroków RUN — nagłówek, split,
lista adresowa oraz scalenie lewego i prawego sąsiada.
- A5 FLOW: osiem kroków RUN mapowanych 1:1 na E01E08.
- A6 STATE: pięć reprezentatywnych stanów E01, E04, E06, E07 i E08.
- A7 RUNTIME: tożsamość źródła/ELF, pamięć `ucHeap` i końcowy werdykt.
- A3, A4 i A8 są jawnie pominięte, ponieważ dublowałyby A2/A5.
Szczegółowa kolejność komend, obserwacji i kryteriów znajduje się w
[`hazard3-iteration-plan.md`](hazard3-iteration-plan.md).
## Wykonane testy
- testy hostowe Task 13;
- budowa RV32I i kontrola symboli ELF;
- Hazard3 RTL: zakończenie kodem 0 po 27308 cyklach;
- osiem checkpointów obecnych w ELF;
- walidacja JSON i odwołań `code_ref`/`snapshot_ref`;
- kontrola PlantUML, SVG, HTML, TeX i siedmiostronicowego PDF;
- TypeScript/React typecheck generatora.
## Pozostaje poza zakresem tej iteracji
- próba na fizycznym RP2350/Pico 2 W;
- commit i publikacja — wymagają osobnego polecenia.
+68
View File
@@ -0,0 +1,68 @@
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#define configCPU_CLOCK_HZ ( 150000000UL )
#define configTICK_RATE_HZ ( 1000U )
#define configMTIME_BASE_ADDRESS ( 0xC0000100UL )
#define configMTIMECMP_BASE_ADDRESS ( 0xC0000108UL )
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_IDLE_HOOK 0
#define configUSE_PASSIVE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configMAX_PRIORITIES 4
#define configMINIMAL_STACK_SIZE 128
#define configMAX_TASK_NAME_LEN 12
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS
#define configIDLE_SHOULD_YIELD 1
#define configNUMBER_OF_CORES 1
#define configTICK_CORE 0
#define configUSE_CORE_AFFINITY 0
#define configRUN_MULTIPLE_PRIORITIES 0
#define configSUPPORT_PICO_SYNC_INTEROP 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configTOTAL_HEAP_SIZE ( 4096U )
#define configAPPLICATION_ALLOCATED_HEAP 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
#define configENABLE_HEAP_PROTECTOR 0
#define configUSE_TIMERS 0
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_TASK_NOTIFICATIONS 1
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_CO_ROUTINES 0
#define configUSE_NEWLIB_REENTRANT 0
#define configUSE_POSIX_ERRNO 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define INCLUDE_vTaskDelay 0
#define INCLUDE_vTaskDelayUntil 0
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskSuspend 0
#define INCLUDE_xTaskGetSchedulerState 0
#define configENABLE_FPU 0
#define configENABLE_VPU 0
#if !defined(PICO_RP2350)
#define configISR_STACK_SIZE_WORDS 128
#endif
#ifndef __ASSEMBLER__
void heap4_lab_assert(const char *file, int line);
#define configASSERT(condition) \
do { if (!(condition)) heap4_lab_assert(__FILE__, __LINE__); } while (0)
#else
#define configASSERT(condition)
#endif
#endif
@@ -0,0 +1,15 @@
#ifndef FREERTOS_RISC_V_CHIP_SPECIFIC_EXTENSIONS_H
#define FREERTOS_RISC_V_CHIP_SPECIFIC_EXTENSIONS_H
/* Hazard3 adds no architectural registers to the base RV32I context. */
#define portasmHAS_MTIME 1
#define portasmHAS_SIFIVE_CLINT 0
#define portasmADDITIONAL_CONTEXT_SIZE 0
.macro portasmSAVE_ADDITIONAL_REGISTERS
.endm
.macro portasmRESTORE_ADDITIONAL_REGISTERS
.endm
#endif
+4
View File
@@ -0,0 +1,4 @@
#ifndef HEAP4_FREESTANDING_STDLIB_H
#define HEAP4_FREESTANDING_STDLIB_H
#include <stddef.h>
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef HEAP4_FREESTANDING_STRING_H
#define HEAP4_FREESTANDING_STRING_H
#include <stddef.h>
void *memcpy(void *destination, const void *source, size_t count);
void *memset(void *destination, int value, size_t count);
size_t strlen(const char *text);
#endif
+50
View File
@@ -0,0 +1,50 @@
#ifndef HEAP4_HOST_FREERTOS_H
#define HEAP4_HOST_FREERTOS_H
#include <stddef.h>
#include <stdint.h>
typedef int BaseType_t;
typedef uintptr_t portPOINTER_SIZE_TYPE;
typedef struct xHeapStats {
size_t xAvailableHeapSpaceInBytes;
size_t xSizeOfLargestFreeBlockInBytes;
size_t xSizeOfSmallestFreeBlockInBytes;
size_t xNumberOfFreeBlocks;
size_t xMinimumEverFreeBytesRemaining;
size_t xNumberOfSuccessfulAllocations;
size_t xNumberOfSuccessfulFrees;
} HeapStats_t;
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE ((size_t)4096U)
#define configAPPLICATION_ALLOCATED_HEAP 1
#define configUSE_MALLOC_FAILED_HOOK 1
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
#define configENABLE_HEAP_PROTECTOR 0
#define portBYTE_ALIGNMENT 8U
#define portBYTE_ALIGNMENT_MASK (portBYTE_ALIGNMENT - 1U)
#define portMAX_DELAY (~(size_t)0U)
#define PRIVILEGED_DATA
#define PRIVILEGED_FUNCTION
#define mtCOVERAGE_TEST_MARKER() do { } while (0)
#define traceMALLOC(pointer, size) do { (void)(pointer); (void)(size); } while (0)
#define traceFREE(pointer, size) do { (void)(pointer); (void)(size); } while (0)
#define taskENTER_CRITICAL() do { } while (0)
#define taskEXIT_CRITICAL() do { } while (0)
void heap4_lab_assert(const char *file, int line);
void vApplicationMallocFailedHook(void);
void *pvPortMalloc(size_t wanted_size);
void vPortFree(void *pointer);
size_t xPortGetFreeHeapSize(void);
size_t xPortGetMinimumEverFreeHeapSize(void);
void vPortGetHeapStats(HeapStats_t *stats);
void vPortHeapResetState(void);
#define configASSERT(condition) \
do { if (!(condition)) heap4_lab_assert(__FILE__, __LINE__); } while (0)
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef HEAP4_HOST_TASK_H
#define HEAP4_HOST_TASK_H
#include "FreeRTOS.h"
void vTaskSuspendAll(void);
BaseType_t xTaskResumeAll(void);
#endif
File diff suppressed because it is too large Load Diff
+1139
View File
File diff suppressed because it is too large Load Diff
-61
View File
@@ -1,61 +0,0 @@
#ifndef HEAP4_COMMON_H
#define HEAP4_COMMON_H
#include <stddef.h>
#include <stdint.h>
#ifdef HOST_PRINTF
#include <stdio.h>
#define TRACE_PRINTF(...) printf(__VA_ARGS__)
#else
#define TRACE_PRINTF(...) ((void)0)
#endif
#define HEAP4_ARRAY_LEN(a) ((int)(sizeof(a) / sizeof((a)[0])))
#define HEAP4_ALIGNMENT ((size_t)8)
#define HEAP4_ALIGNMENT_MASK (HEAP4_ALIGNMENT - 1U)
#define HEAP4_ALLOCATED_BIT ((size_t)1U << (sizeof(size_t) * 8U - 1U))
typedef struct HeapBlock {
struct HeapBlock *next;
size_t size;
} HeapBlock;
static inline size_t heap4_align_up(size_t value)
{
if ((value & HEAP4_ALIGNMENT_MASK) != 0U)
value += HEAP4_ALIGNMENT - (value & HEAP4_ALIGNMENT_MASK);
return value;
}
static inline uintptr_t heap4_align_address(uintptr_t address)
{
uintptr_t mask;
mask = (uintptr_t)HEAP4_ALIGNMENT_MASK;
if ((address & mask) != 0U)
address += (uintptr_t)HEAP4_ALIGNMENT - (address & mask);
return address;
}
static inline size_t heap4_clear_allocated(size_t size)
{
return size & ~HEAP4_ALLOCATED_BIT;
}
static inline size_t heap4_mark_allocated(size_t size)
{
return size | HEAP4_ALLOCATED_BIT;
}
static inline int heap4_is_allocated(size_t size)
{
return (size & HEAP4_ALLOCATED_BIT) != 0U;
}
static inline int heap4_blocks_touch(HeapBlock *left, HeapBlock *right)
{
return (uint8_t *)left + heap4_clear_allocated(left->size) == (uint8_t *)right;
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef HEAP4_MODEL_H
#define HEAP4_MODEL_H
#include <stddef.h>
#include <stdint.h>
#define MODEL_ALIGNMENT ((size_t)8U)
typedef struct ModelBlock ModelBlock;
struct ModelBlock {
ModelBlock *next;
size_t size;
};
static inline size_t model_align_up(size_t value)
{
return (value + MODEL_ALIGNMENT - 1U) & ~(MODEL_ALIGNMENT - 1U);
}
#if defined(HOST_PRINTF)
#include <stdio.h>
#endif
#endif
+72
View File
@@ -0,0 +1,72 @@
#include "heap4_model.h"
enum {
ARENA_BYTES = 256,
REQUEST_BYTES = 13,
WANTED_BYTES = (sizeof(ModelBlock) + REQUEST_BYTES + 7U) & ~7U
};
typedef struct {
ModelBlock allocated;
uint8_t payload[WANTED_BYTES - sizeof(ModelBlock)];
ModelBlock remainder;
uint8_t free_payload[ARENA_BYTES - WANTED_BYTES - sizeof(ModelBlock)];
} SplitArena;
typedef union {
uint64_t force_alignment;
SplitArena blocks;
} AlignedSplitArena;
AlignedSplitArena g_split_arena;
ModelBlock *g_free_head;
volatile size_t g_header_bytes;
volatile size_t g_wanted_bytes;
volatile size_t g_remainder_bytes;
volatile size_t g_payload_offset;
volatile int g_split_addresses_aligned;
volatile int g_task01_pass;
__attribute__((noinline)) void task01_debug_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
int main(void)
{
SplitArena *arena = &g_split_arena.blocks;
uintptr_t base = (uintptr_t)&arena->allocated;
uintptr_t remainder = (uintptr_t)&arena->remainder;
arena->allocated.next = NULL;
arena->allocated.size = WANTED_BYTES;
arena->remainder.next = NULL;
arena->remainder.size = ARENA_BYTES - WANTED_BYTES;
arena->payload[0] = (uint8_t)'A';
g_free_head = &arena->remainder;
g_header_bytes = sizeof(ModelBlock);
g_wanted_bytes = WANTED_BYTES;
g_remainder_bytes = arena->remainder.size;
g_payload_offset = (size_t)((uintptr_t)&arena->payload[0] - base);
g_split_addresses_aligned =
(base % MODEL_ALIGNMENT) == 0U &&
(remainder % MODEL_ALIGNMENT) == 0U;
g_task01_pass =
g_wanted_bytes == model_align_up(sizeof(ModelBlock) + REQUEST_BYTES) &&
(size_t)(remainder - base) == g_wanted_bytes &&
g_remainder_bytes + g_wanted_bytes == ARENA_BYTES &&
g_payload_offset == sizeof(ModelBlock) &&
g_split_addresses_aligned;
task01_debug_checkpoint();
#if defined(HOST_PRINTF)
printf("header=%zu wanted=%zu remainder=%zu payload=%zu aligned=%d pass=%d\n",
g_header_bytes, g_wanted_bytes, g_remainder_bytes,
g_payload_offset, g_split_addresses_aligned, g_task01_pass);
#endif
return g_task01_pass ? 0 : 1;
}
-29
View File
@@ -1,29 +0,0 @@
#include "heap4_common.h"
volatile size_t g_header_size;
volatile size_t g_aligned_header_size;
volatile size_t g_allocated_bit_set;
volatile size_t g_user_bytes;
volatile size_t g_total_block_bytes;
int main(void)
{
HeapBlock block;
size_t requested;
requested = 13U;
block.next = 0;
block.size = heap4_mark_allocated(heap4_align_up(requested + sizeof(HeapBlock)));
g_header_size = sizeof(HeapBlock);
g_aligned_header_size = heap4_align_up(sizeof(HeapBlock));
g_allocated_bit_set = heap4_is_allocated(block.size);
g_total_block_bytes = heap4_clear_allocated(block.size);
g_user_bytes = g_total_block_bytes - sizeof(HeapBlock);
TRACE_PRINTF("header=%u aligned=%u allocated=%u total=%u user=%u\n",
(unsigned)g_header_size, (unsigned)g_aligned_header_size,
(unsigned)g_allocated_bit_set, (unsigned)g_total_block_bytes,
(unsigned)g_user_bytes);
return 0;
}
+136
View File
@@ -0,0 +1,136 @@
#include "heap4_model.h"
enum { BLOCK_BYTES = 48 };
typedef struct {
ModelBlock first;
uint8_t first_payload[BLOCK_BYTES - sizeof(ModelBlock)];
ModelBlock middle;
uint8_t middle_payload[BLOCK_BYTES - sizeof(ModelBlock)];
ModelBlock last;
uint8_t last_payload[BLOCK_BYTES - sizeof(ModelBlock)];
} CoalesceArena;
typedef union {
uint64_t force_alignment;
CoalesceArena blocks;
} AlignedCoalesceArena;
AlignedCoalesceArena g_coalesce_arena;
ModelBlock *g_free_head;
volatile size_t g_before_nodes;
volatile size_t g_before_total;
volatile size_t g_before_largest;
volatile size_t g_after_nodes;
volatile size_t g_after_total;
volatile size_t g_after_largest;
volatile int g_task02_pass;
static void insert_and_coalesce(ModelBlock *block)
{
ModelBlock *previous = NULL;
ModelBlock *current = g_free_head;
while (current != NULL && (uintptr_t)current < (uintptr_t)block)
{
previous = current;
current = current->next;
}
block->next = current;
if (current != NULL &&
(uint8_t *)block + block->size == (uint8_t *)current)
{
block->size += current->size;
block->next = current->next;
}
if (previous != NULL &&
(uint8_t *)previous + previous->size == (uint8_t *)block)
{
previous->size += block->size;
previous->next = block->next;
}
else if (previous != NULL)
{
previous->next = block;
}
else
{
g_free_head = block;
}
}
static void measure(size_t *nodes, size_t *total, size_t *largest)
{
ModelBlock *block;
*nodes = 0U;
*total = 0U;
*largest = 0U;
for (block = g_free_head; block != NULL; block = block->next)
{
(*nodes)++;
*total += block->size;
if (block->size > *largest)
{
*largest = block->size;
}
}
}
__attribute__((noinline)) void task02_fragmented_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void task02_debug_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
int main(void)
{
CoalesceArena *arena = &g_coalesce_arena.blocks;
size_t nodes;
size_t total;
size_t largest;
arena->first.size = BLOCK_BYTES;
arena->middle.size = BLOCK_BYTES;
arena->last.size = BLOCK_BYTES;
g_free_head = NULL;
insert_and_coalesce(&arena->first);
insert_and_coalesce(&arena->last);
measure(&nodes, &total, &largest);
g_before_nodes = nodes;
g_before_total = total;
g_before_largest = largest;
task02_fragmented_checkpoint();
insert_and_coalesce(&arena->middle);
measure(&nodes, &total, &largest);
g_after_nodes = nodes;
g_after_total = total;
g_after_largest = largest;
g_task02_pass =
g_before_nodes == 2U && g_before_total == 96U &&
g_before_largest == 48U && g_after_nodes == 1U &&
g_after_total == 144U && g_after_largest == 144U &&
g_free_head == &arena->first && g_free_head->next == NULL;
task02_debug_checkpoint();
#if defined(HOST_PRINTF)
printf("before_nodes=%zu before_total=%zu before_largest=%zu "
"after_nodes=%zu after_total=%zu after_largest=%zu pass=%d\n",
g_before_nodes, g_before_total, g_before_largest,
g_after_nodes, g_after_total, g_after_largest, g_task02_pass);
#endif
return g_task02_pass ? 0 : 1;
}
-64
View File
@@ -1,64 +0,0 @@
#include "heap4_common.h"
volatile size_t g_free_total;
volatile size_t g_largest_free;
volatile int g_node_count;
static size_t list_total(HeapBlock *start)
{
HeapBlock *block;
size_t total;
total = 0U;
for (block = start->next; block != 0; block = block->next)
total += block->size;
return total;
}
static size_t list_largest(HeapBlock *start)
{
HeapBlock *block;
size_t largest;
largest = 0U;
for (block = start->next; block != 0; block = block->next)
if (block->size > largest)
largest = block->size;
return largest;
}
static int list_count(HeapBlock *start)
{
HeapBlock *block;
int count;
count = 0;
for (block = start->next; block != 0; block = block->next)
count++;
return count;
}
int main(void)
{
HeapBlock start;
HeapBlock a;
HeapBlock b;
HeapBlock c;
start.next = &a;
start.size = 0U;
a.next = &b;
a.size = 32U;
b.next = &c;
b.size = 80U;
c.next = 0;
c.size = 24U;
g_free_total = list_total(&start);
g_largest_free = list_largest(&start);
g_node_count = list_count(&start);
TRACE_PRINTF("free=%u largest=%u count=%d\n",
(unsigned)g_free_total, (unsigned)g_largest_free, g_node_count);
return 0;
}
+229
View File
@@ -0,0 +1,229 @@
#include <stddef.h>
#include <stdint.h>
#include "FreeRTOS.h"
#include "task.h"
#if defined(HOST_PRINTF)
#include <stdio.h>
#endif
uint8_t ucHeap[configTOTAL_HEAP_SIZE] __attribute__((aligned(portBYTE_ALIGNMENT)));
HeapStats_t g_initial_stats;
HeapStats_t g_after_a_stats;
HeapStats_t g_after_b_stats;
HeapStats_t g_after_allocations_stats;
HeapStats_t g_after_free_a_stats;
HeapStats_t g_fragmented_stats;
HeapStats_t g_final_stats;
volatile size_t g_initial_free;
volatile size_t g_after_a_free;
volatile size_t g_after_b_free;
volatile size_t g_after_allocations;
volatile size_t g_after_free_a;
volatile size_t g_fragmented_free;
volatile size_t g_final_free;
volatile size_t g_minimum_ever_free;
volatile size_t g_a_consumed;
volatile size_t g_b_consumed;
volatile size_t g_c_consumed;
void * volatile g_probe;
void * volatile g_a;
void * volatile g_b;
void * volatile g_c;
void * volatile g_too_large;
volatile int g_a_aligned;
volatile int g_b_aligned;
volatile int g_c_aligned;
volatile int g_allocations_aligned;
volatile int g_oom_is_null;
volatile int g_malloc_failed_hooks;
volatile int g_assert_failures;
volatile int g_rv32_layout_expected;
volatile int g_task03_pass;
void vApplicationMallocFailedHook(void)
{
g_malloc_failed_hooks++;
}
void heap4_lab_assert(const char *file, int line)
{
(void)file;
(void)line;
g_assert_failures++;
}
#if defined(HEAP4_HOST_ADAPTER)
void vTaskSuspendAll(void)
{
}
BaseType_t xTaskResumeAll(void)
{
return 0;
}
#endif
__attribute__((noinline)) void heap4_reset_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_alloc_a_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_alloc_b_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_alloc_c_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_free_a_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_fragmented_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void heap4_coalesced_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
__attribute__((noinline)) void task03_debug_checkpoint(void)
{
#if defined(__GNUC__)
__asm__ volatile("" ::: "memory");
#endif
}
int main(void)
{
vPortHeapResetState();
g_probe = pvPortMalloc(1U);
if (g_probe != NULL)
{
vPortFree(g_probe);
}
g_initial_free = xPortGetFreeHeapSize();
vPortGetHeapStats(&g_initial_stats);
heap4_reset_checkpoint();
g_a = pvPortMalloc(24U);
g_after_a_free = xPortGetFreeHeapSize();
g_a_consumed = g_initial_free - g_after_a_free;
g_a_aligned =
g_a != NULL && ((uintptr_t)g_a % portBYTE_ALIGNMENT) == 0U;
vPortGetHeapStats(&g_after_a_stats);
heap4_alloc_a_checkpoint();
g_b = pvPortMalloc(40U);
g_after_b_free = xPortGetFreeHeapSize();
g_b_consumed = g_after_a_free - g_after_b_free;
g_b_aligned =
g_b != NULL && ((uintptr_t)g_b % portBYTE_ALIGNMENT) == 0U;
vPortGetHeapStats(&g_after_b_stats);
heap4_alloc_b_checkpoint();
g_c = pvPortMalloc(16U);
g_after_allocations = xPortGetFreeHeapSize();
g_c_consumed = g_after_b_free - g_after_allocations;
g_c_aligned =
g_c != NULL && ((uintptr_t)g_c % portBYTE_ALIGNMENT) == 0U;
g_allocations_aligned =
g_a_aligned && g_b_aligned && g_c_aligned;
vPortGetHeapStats(&g_after_allocations_stats);
heap4_alloc_c_checkpoint();
vPortFree(g_a);
g_after_free_a = xPortGetFreeHeapSize();
vPortGetHeapStats(&g_after_free_a_stats);
heap4_free_a_checkpoint();
vPortFree(g_c);
g_fragmented_free = xPortGetFreeHeapSize();
vPortGetHeapStats(&g_fragmented_stats);
heap4_fragmented_checkpoint();
vPortFree(g_b);
g_final_free = xPortGetFreeHeapSize();
g_minimum_ever_free = xPortGetMinimumEverFreeHeapSize();
vPortGetHeapStats(&g_final_stats);
heap4_coalesced_checkpoint();
g_too_large = pvPortMalloc(configTOTAL_HEAP_SIZE * 2U);
g_oom_is_null = g_too_large == NULL;
#if defined(__riscv) && (__riscv_xlen == 32)
g_rv32_layout_expected =
portBYTE_ALIGNMENT == 16U &&
g_initial_free == 4080U &&
g_after_a_free == 4032U && g_a_consumed == 48U &&
g_after_b_free == 3968U && g_b_consumed == 64U &&
g_after_allocations == 3936U && g_c_consumed == 32U &&
g_after_free_a == 3984U &&
g_fragmented_free == 4016U &&
g_final_free == 4080U;
#else
g_rv32_layout_expected = 1;
#endif
g_task03_pass =
g_probe != NULL && g_allocations_aligned &&
g_rv32_layout_expected &&
g_initial_stats.xNumberOfFreeBlocks == 1U &&
g_after_a_free < g_initial_free &&
g_after_b_free < g_after_a_free &&
g_initial_free > g_after_allocations &&
g_after_free_a > g_after_allocations &&
g_fragmented_free > g_after_free_a &&
g_final_free == g_initial_free &&
g_minimum_ever_free <= g_after_allocations &&
g_after_free_a_stats.xNumberOfFreeBlocks == 2U &&
g_fragmented_stats.xNumberOfFreeBlocks == 2U &&
g_fragmented_stats.xAvailableHeapSpaceInBytes >
g_fragmented_stats.xSizeOfLargestFreeBlockInBytes &&
g_final_stats.xNumberOfFreeBlocks == 1U &&
g_final_stats.xSizeOfLargestFreeBlockInBytes == g_initial_free &&
g_oom_is_null && g_malloc_failed_hooks == 1 &&
g_assert_failures == 0;
task03_debug_checkpoint();
#if defined(HOST_PRINTF)
printf("initial=%zu after_a=%zu after_b=%zu after_c=%zu "
"free_a=%zu fragmented=%zu final=%zu min=%zu "
"consumed=%zu/%zu/%zu aligned=%d oom=%d hooks=%d "
"asserts=%d pass=%d\n",
g_initial_free, g_after_a_free, g_after_b_free,
g_after_allocations, g_after_free_a, g_fragmented_free,
g_final_free, g_minimum_ever_free,
g_a_consumed, g_b_consumed, g_c_consumed,
g_allocations_aligned, g_oom_is_null,
g_malloc_failed_hooks, g_assert_failures, g_task03_pass);
#endif
return g_task03_pass ? 0 : 1;
}
-49
View File
@@ -1,49 +0,0 @@
#include "heap4_common.h"
#define HEAP_BYTES 160U
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
static HeapBlock start;
static HeapBlock *end_marker;
volatile size_t g_initial_free_size;
volatile uintptr_t g_aligned_offset;
volatile int g_end_is_last;
static void heap_init(void)
{
uintptr_t raw;
uintptr_t aligned;
size_t available;
HeapBlock *first;
raw = (uintptr_t)&heap_area[0];
aligned = heap4_align_address(raw);
available = HEAP_BYTES - (size_t)(aligned - raw);
available &= ~HEAP4_ALIGNMENT_MASK;
first = (HeapBlock *)aligned;
end_marker = (HeapBlock *)(aligned + available - sizeof(HeapBlock));
end_marker->next = 0;
end_marker->size = 0U;
first->next = end_marker;
first->size = (uint8_t *)end_marker - (uint8_t *)first;
start.next = first;
start.size = 0U;
}
int main(void)
{
heap_init();
g_aligned_offset = (uintptr_t)start.next - (uintptr_t)&heap_area[0];
g_initial_free_size = start.next->size;
g_end_is_last = (start.next->next == end_marker) && (end_marker->next == 0);
TRACE_PRINTF("offset=%u free=%u end_last=%d\n",
(unsigned)g_aligned_offset, (unsigned)g_initial_free_size,
g_end_is_last);
return 0;
}
-26
View File
@@ -1,26 +0,0 @@
#include "heap4_common.h"
volatile size_t g_request_1;
volatile size_t g_request_9;
volatile size_t g_request_17;
volatile uintptr_t g_address_delta;
int main(void)
{
uint8_t bytes[32];
uintptr_t raw;
uintptr_t aligned;
g_request_1 = heap4_align_up(1U + sizeof(HeapBlock));
g_request_9 = heap4_align_up(9U + sizeof(HeapBlock));
g_request_17 = heap4_align_up(17U + sizeof(HeapBlock));
raw = (uintptr_t)&bytes[1];
aligned = heap4_align_address(raw);
g_address_delta = aligned - raw;
TRACE_PRINTF("r1=%u r9=%u r17=%u delta=%u\n",
(unsigned)g_request_1, (unsigned)g_request_9,
(unsigned)g_request_17, (unsigned)g_address_delta);
return 0;
}
-73
View File
@@ -1,73 +0,0 @@
#include "heap4_common.h"
#define HEAP_BYTES 128U
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
static HeapBlock start;
static HeapBlock *end_marker;
volatile size_t g_allocated_size;
volatile size_t g_remaining_free;
volatile int g_allocation_ok;
static void heap_init_one_block(void)
{
uintptr_t raw;
uintptr_t aligned;
HeapBlock *first;
raw = (uintptr_t)&heap_area[0];
aligned = heap4_align_address(raw);
first = (HeapBlock *)aligned;
end_marker = (HeapBlock *)(aligned + 120U);
end_marker->next = 0;
end_marker->size = 0U;
first->next = end_marker;
first->size = (uint8_t *)end_marker - (uint8_t *)first;
start.next = first;
start.size = 0U;
}
static void *heap_malloc_whole_block(size_t wanted)
{
HeapBlock *previous;
HeapBlock *block;
size_t total;
total = heap4_align_up(wanted + sizeof(HeapBlock));
previous = &start;
block = start.next;
while (block != end_marker) {
if (block->size >= total) {
previous->next = block->next;
block->next = 0;
block->size = heap4_mark_allocated(block->size);
return (uint8_t *)block + sizeof(HeapBlock);
}
previous = block;
block = block->next;
}
return 0;
}
int main(void)
{
void *p;
HeapBlock *allocated;
heap_init_one_block();
p = heap_malloc_whole_block(24U);
allocated = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
g_allocation_ok = p != 0;
g_allocated_size = heap4_clear_allocated(allocated->size);
g_remaining_free = start.next->size;
TRACE_PRINTF("ok=%d allocated=%u remaining=%u\n",
g_allocation_ok, (unsigned)g_allocated_size,
(unsigned)g_remaining_free);
return 0;
}
-93
View File
@@ -1,93 +0,0 @@
#include "heap4_common.h"
#define HEAP_BYTES 192U
#define MIN_SPLIT_SIZE ((size_t)(sizeof(HeapBlock) * 2U))
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
static HeapBlock start;
static HeapBlock *end_marker;
volatile size_t g_allocated_size;
volatile size_t g_split_free_size;
volatile int g_free_nodes;
static void heap_init_one_block(void)
{
uintptr_t aligned;
HeapBlock *first;
aligned = heap4_align_address((uintptr_t)&heap_area[0]);
first = (HeapBlock *)aligned;
end_marker = (HeapBlock *)(aligned + 176U);
end_marker->next = 0;
end_marker->size = 0U;
first->next = end_marker;
first->size = (uint8_t *)end_marker - (uint8_t *)first;
start.next = first;
start.size = 0U;
}
static void *heap_malloc_split(size_t wanted)
{
HeapBlock *previous;
HeapBlock *block;
HeapBlock *remainder;
size_t total;
size_t original;
total = heap4_align_up(wanted + sizeof(HeapBlock));
previous = &start;
block = start.next;
while (block != end_marker) {
if (block->size >= total) {
original = block->size;
if (original - total > MIN_SPLIT_SIZE) {
remainder = (HeapBlock *)((uint8_t *)block + total);
remainder->size = original - total;
remainder->next = block->next;
previous->next = remainder;
block->size = total;
} else {
previous->next = block->next;
}
block->next = 0;
block->size = heap4_mark_allocated(block->size);
return (uint8_t *)block + sizeof(HeapBlock);
}
previous = block;
block = block->next;
}
return 0;
}
static int count_free_nodes(void)
{
HeapBlock *block;
int count;
count = 0;
for (block = start.next; block != end_marker; block = block->next)
count++;
return count;
}
int main(void)
{
void *p;
HeapBlock *allocated;
heap_init_one_block();
p = heap_malloc_split(32U);
allocated = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
g_allocated_size = heap4_clear_allocated(allocated->size);
g_split_free_size = start.next->size;
g_free_nodes = count_free_nodes();
TRACE_PRINTF("allocated=%u split=%u nodes=%d\n",
(unsigned)g_allocated_size, (unsigned)g_split_free_size,
g_free_nodes);
return 0;
}
-88
View File
@@ -1,88 +0,0 @@
#include "heap4_common.h"
static uint8_t heap_area[192];
static HeapBlock start;
static HeapBlock *end_marker;
volatile int g_order_ok;
volatile int g_free_count;
volatile size_t g_total_free;
static void insert_block(HeapBlock *block)
{
HeapBlock *iterator;
for (iterator = &start; iterator->next < block; iterator = iterator->next)
;
block->next = iterator->next;
iterator->next = block;
}
static void heap_free_model(void *p)
{
HeapBlock *block;
if (p == 0)
return;
block = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
block->size = heap4_clear_allocated(block->size);
insert_block(block);
}
static int count_free(void)
{
HeapBlock *block;
int count;
count = 0;
for (block = start.next; block != end_marker; block = block->next)
count++;
return count;
}
static size_t total_free(void)
{
HeapBlock *block;
size_t total;
total = 0U;
for (block = start.next; block != end_marker; block = block->next)
total += block->size;
return total;
}
int main(void)
{
HeapBlock *a;
HeapBlock *b;
HeapBlock *c;
void *payload;
a = (HeapBlock *)&heap_area[0];
b = (HeapBlock *)&heap_area[64];
c = (HeapBlock *)&heap_area[128];
end_marker = (HeapBlock *)&heap_area[176];
start.next = a;
a->next = c;
c->next = end_marker;
end_marker->next = 0;
a->size = 40U;
b->size = heap4_mark_allocated(32U);
c->size = 48U;
end_marker->size = 0U;
payload = (uint8_t *)b + sizeof(HeapBlock);
heap_free_model(payload);
g_order_ok = start.next == a && a->next == b && b->next == c && c->next == end_marker;
g_free_count = count_free();
g_total_free = total_free();
TRACE_PRINTF("order=%d count=%d total=%u\n",
g_order_ok, g_free_count, (unsigned)g_total_free);
return 0;
}
-76
View File
@@ -1,76 +0,0 @@
#include "heap4_common.h"
static uint8_t heap_area[192];
static HeapBlock start;
static HeapBlock *end_marker;
volatile int g_free_count;
volatile size_t g_merged_size;
volatile int g_merged_with_right;
static void insert_block_merge(HeapBlock *block)
{
HeapBlock *iterator;
uint8_t *block_end;
for (iterator = &start; iterator->next < block; iterator = iterator->next)
;
block_end = (uint8_t *)block + block->size;
if (block_end == (uint8_t *)iterator->next) {
block->size += iterator->next->size;
block->next = iterator->next->next;
} else {
block->next = iterator->next;
}
if (iterator != &start && heap4_blocks_touch(iterator, block)) {
iterator->size += block->size;
iterator->next = block->next;
} else {
iterator->next = block;
}
}
static int count_free(void)
{
HeapBlock *block;
int count;
count = 0;
for (block = start.next; block != end_marker; block = block->next)
count++;
return count;
}
int main(void)
{
HeapBlock *left;
HeapBlock *middle;
HeapBlock *right;
left = (HeapBlock *)&heap_area[0];
middle = (HeapBlock *)&heap_area[48];
right = (HeapBlock *)&heap_area[96];
end_marker = (HeapBlock *)&heap_area[160];
start.next = left;
left->next = right;
right->next = end_marker;
end_marker->next = 0;
left->size = 48U;
middle->size = 48U;
right->size = 64U;
end_marker->size = 0U;
insert_block_merge(middle);
g_free_count = count_free();
g_merged_size = start.next->size;
g_merged_with_right = start.next->next == end_marker;
TRACE_PRINTF("count=%d size=%u merged_right=%d\n",
g_free_count, (unsigned)g_merged_size, g_merged_with_right);
return 0;
}
-34
View File
@@ -1,34 +0,0 @@
#include "heap4_common.h"
#ifndef CONFIG_TOTAL_HEAP_SIZE
#define CONFIG_TOTAL_HEAP_SIZE 256U
#endif
#ifndef CONFIG_SUPPORT_DYNAMIC_ALLOCATION
#define CONFIG_SUPPORT_DYNAMIC_ALLOCATION 1
#endif
#define CONFIG_ADJUSTED_HEAP_SIZE (CONFIG_TOTAL_HEAP_SIZE - HEAP4_ALIGNMENT)
volatile size_t g_total_heap;
volatile size_t g_adjusted_heap;
volatile int g_dynamic_enabled;
volatile int g_trace_is_host_only;
int main(void)
{
g_total_heap = CONFIG_TOTAL_HEAP_SIZE;
g_adjusted_heap = CONFIG_ADJUSTED_HEAP_SIZE;
g_dynamic_enabled = CONFIG_SUPPORT_DYNAMIC_ALLOCATION;
#ifdef HOST_PRINTF
g_trace_is_host_only = 1;
#else
g_trace_is_host_only = 0;
#endif
TRACE_PRINTF("heap=%u adjusted=%u dynamic=%d host_trace=%d\n",
(unsigned)g_total_heap, (unsigned)g_adjusted_heap,
g_dynamic_enabled, g_trace_is_host_only);
return 0;
}
-175
View File
@@ -1,175 +0,0 @@
#include "heap4_common.h"
#define HEAP_BYTES 256U
#define MIN_SPLIT_SIZE ((size_t)(sizeof(HeapBlock) * 2U))
static uint8_t heap_area[HEAP_BYTES + HEAP4_ALIGNMENT];
static HeapBlock start;
static HeapBlock *end_marker;
volatile int g_allocations_ok;
volatile int g_final_free_nodes;
volatile size_t g_final_free_total;
volatile size_t g_minimum_ever_free;
static size_t free_bytes_remaining;
static size_t minimum_ever_free;
static size_t list_total(void)
{
HeapBlock *block;
size_t total;
total = 0U;
for (block = start.next; block != end_marker; block = block->next)
total += block->size;
return total;
}
static int list_count(void)
{
HeapBlock *block;
int count;
count = 0;
for (block = start.next; block != end_marker; block = block->next)
count++;
return count;
}
static void insert_block_merge(HeapBlock *block)
{
HeapBlock *iterator;
uint8_t *block_end;
for (iterator = &start; iterator->next < block; iterator = iterator->next)
;
block_end = (uint8_t *)block + block->size;
if (block_end == (uint8_t *)iterator->next) {
block->size += iterator->next->size;
block->next = iterator->next->next;
} else {
block->next = iterator->next;
}
if (iterator != &start && heap4_blocks_touch(iterator, block)) {
iterator->size += block->size;
iterator->next = block->next;
} else {
iterator->next = block;
}
}
static void heap_init(void)
{
uintptr_t raw;
uintptr_t aligned;
size_t available;
HeapBlock *first;
raw = (uintptr_t)&heap_area[0];
aligned = heap4_align_address(raw);
available = HEAP_BYTES - (size_t)(aligned - raw);
available &= ~HEAP4_ALIGNMENT_MASK;
first = (HeapBlock *)aligned;
end_marker = (HeapBlock *)(aligned + available - sizeof(HeapBlock));
end_marker->next = 0;
end_marker->size = 0U;
first->next = end_marker;
first->size = (uint8_t *)end_marker - (uint8_t *)first;
start.next = first;
start.size = 0U;
free_bytes_remaining = first->size;
minimum_ever_free = free_bytes_remaining;
}
static void *heap_malloc_model(size_t wanted)
{
HeapBlock *previous;
HeapBlock *block;
HeapBlock *remainder;
size_t total;
size_t original;
if (wanted == 0U)
return 0;
total = heap4_align_up(wanted + sizeof(HeapBlock));
previous = &start;
block = start.next;
while (block != end_marker) {
if (block->size >= total) {
original = block->size;
if (original - total > MIN_SPLIT_SIZE) {
remainder = (HeapBlock *)((uint8_t *)block + total);
remainder->size = original - total;
remainder->next = block->next;
previous->next = remainder;
block->size = total;
} else {
previous->next = block->next;
total = original;
}
block->next = 0;
block->size = heap4_mark_allocated(block->size);
free_bytes_remaining -= total;
if (free_bytes_remaining < minimum_ever_free)
minimum_ever_free = free_bytes_remaining;
return (uint8_t *)block + sizeof(HeapBlock);
}
previous = block;
block = block->next;
}
return 0;
}
static void heap_free_model(void *p)
{
HeapBlock *block;
size_t size;
if (p == 0)
return;
block = (HeapBlock *)((uint8_t *)p - sizeof(HeapBlock));
if (!heap4_is_allocated(block->size))
return;
size = heap4_clear_allocated(block->size);
block->size = size;
free_bytes_remaining += size;
insert_block_merge(block);
}
int main(void)
{
void *a;
void *b;
void *c;
heap_init();
a = heap_malloc_model(24U);
b = heap_malloc_model(40U);
heap_free_model(a);
c = heap_malloc_model(16U);
heap_free_model(b);
heap_free_model(c);
g_allocations_ok = a != 0 && b != 0 && c != 0;
g_final_free_nodes = list_count();
g_final_free_total = list_total();
g_minimum_ever_free = minimum_ever_free;
TRACE_PRINTF("ok=%d nodes=%d free=%u min=%u\n",
g_allocations_ok, g_final_free_nodes,
(unsigned)g_final_free_total, (unsigned)g_minimum_ever_free);
return 0;
}
+19
View File
@@ -0,0 +1,19 @@
schema: 1
targets:
native:
profile: native-amd64
actions: [build, test, run, debug]
hazard3-baremetal:
profile: hazard3-sim
actions: [build, test, run, debug]
rp2350-rv:
profile: rp2350
actions: [build, test, deploy, debug]
actions:
build: [bash, tools/card-action.sh, build]
test: [bash, tools/card-action.sh, test]
run: [bash, tools/card-action.sh, run]
deploy: [bash, tools/card-action.sh, deploy]
debug: [bash, tools/card-action.sh, debug]
artifacts:
directory: .stem/artifacts
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
elf="${1:?usage: check_task03_elf.sh ELF [tool-prefix]}"
prefix="${2:-riscv64-unknown-elf-}"
nm="${prefix}nm"
objdump="${prefix}objdump"
test -s "$elf"
for symbol in pvPortMalloc vPortFree prvInsertBlockIntoFreeList ucHeap \
heap4_reset_checkpoint heap4_alloc_a_checkpoint \
heap4_alloc_b_checkpoint heap4_alloc_c_checkpoint \
heap4_free_a_checkpoint heap4_fragmented_checkpoint \
heap4_coalesced_checkpoint task03_debug_checkpoint \
g_initial_stats g_after_allocations_stats g_fragmented_stats \
g_final_stats g_rv32_layout_expected g_task03_pass; do
"$nm" -a "$elf" | grep -E "[[:space:]]${symbol}$" >/dev/null
done
"$objdump" -d "$elf" | grep -E 'addi[[:space:]]+sp,sp,-' >/dev/null
printf 'PASS Task 3 links upstream heap_4 and eight observable checkpoints: %s\n' "$elf"
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail
root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
make -C "$root" PROFILE=observe host >/dev/null
check_output() {
local program="$1" expected="$2" actual
actual="$($program)"
if [[ "$actual" != "$expected" ]]; then
printf 'FAIL %s\nexpected: %s\nactual: %s\n' "$program" "$expected" "$actual" >&2
return 1
fi
printf 'PASS %s: %s\n' "$(basename -- "$(dirname -- "$program")")" "$actual"
}
check_output "$root/host-build/task01_first_fit_split/prog" \
'header=16 wanted=32 remainder=224 payload=16 aligned=1 pass=1'
check_output "$root/host-build/task02_address_order_coalesce/prog" \
'before_nodes=2 before_total=96 before_largest=48 after_nodes=1 after_total=144 after_largest=144 pass=1'
check_output "$root/host-build/task03_freertos_heap4/prog" \
'initial=4080 after_a=4040 after_b=3984 after_c=3952 free_a=3992 fragmented=4024 final=4080 min=3952 consumed=40/56/32 aligned=1 oom=1 hooks=1 asserts=0 pass=1'
+364
View File
@@ -0,0 +1,364 @@
#!/usr/bin/env bash
set -euo pipefail
action="${1:?action is required}"
root="${STEM_REPO:-$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)}"
profile="${STEM_PROFILE:-native-amd64}"
target="${STEM_TARGET:-native}"
selector="${STEM_TASK:-task3}"
state="${STEM_STATE_DIR:-$root/.stem/instances/local}"
tasks=(
task01_first_fit_split
task02_address_order_coalesce
task03_freertos_heap4
)
resolve_task() {
local value="${1,,}" digits number stem
for stem in "${tasks[@]}"; do
if [[ "$value" == "$stem" ]]; then
printf '%s\n' "$stem"
return
fi
done
if [[ "$value" =~ ^(task|t)?[-_]?0*([1-3])($|[-_].*) ]]; then
digits="${BASH_REMATCH[2]}"
number=$((10#$digits))
printf '%s\n' "${tasks[number - 1]}"
return
fi
printf 'Unknown task selector: %s\n' "$1" >&2
exit 2
}
task_stem="$(resolve_task "$selector")"
task_digits="${task_stem#task}"
task_digits="${task_digits%%_*}"
task_number=$((10#$task_digits))
task_key="$(printf 'task%02d' "$task_number")"
source_file="$root/src/tasks/$task_stem.c"
artifact_dir="$root/.stem/artifacts/$profile/$target/$task_key"
mkdir -p "$state" "$artifact_dir"
freertos_kernel_path() {
if [[ -n "${FREERTOS_KERNEL_PATH:-}" ]]; then
printf '%s\n' "$FREERTOS_KERNEL_PATH"
elif [[ -f /opt/FreeRTOS-Kernel/portable/MemMang/heap_4.c ]]; then
printf '%s\n' /opt/FreeRTOS-Kernel
else
printf '%s\n' "$root/../lab-rv32i-freertos-task-stack-vector/vendor/FreeRTOS-Kernel"
fi
}
verify_kernel() {
local kernel="$1"
test -f "$kernel/portable/MemMang/heap_4.c"
grep -F 'FreeRTOS Kernel V11.3.0' "$kernel/include/FreeRTOS.h" >/dev/null
}
freertos_rp2350_path() {
if [[ -n "${FREERTOS_RP2350_PATH:-}" ]]; then
printf '%s\n' "$FREERTOS_RP2350_PATH"
else
printf '%s\n' /opt/FreeRTOS-RP2350
fi
}
verify_rp2350_kernel() {
local kernel="$1"
test -f "$kernel/portable/ThirdParty/GCC/RP2350_RISC-V/portASM.S"
grep -F '<DEVELOPMENT BRANCH>' "$kernel/include/FreeRTOS.h" >/dev/null
}
copy_artifact() {
local path="$1"
[[ -f "$path" ]] && cp -f "$path" "$artifact_dir/"
}
build_native() {
local mode="${1:-normal}" kernel build_dir output cc="${CC:-cc}"
local flags=(-std=c11 -O0 -g3 -fno-omit-frame-pointer -fno-inline
-fno-optimize-sibling-calls -Wall -Wextra -Wpedantic
-DHOST_PRINTF=1 -I"$root/src/tasks")
build_dir="$state/build/native/$task_stem"
output="$build_dir/prog"
if [[ "$mode" == sanitizer ]]; then
flags+=(-fsanitize=address,undefined)
fi
mkdir -p "$build_dir"
if [[ "$task_number" -eq 3 ]]; then
kernel="$(freertos_kernel_path)"
verify_kernel "$kernel"
flags+=(-DHEAP4_HOST_ADAPTER=1 -I"$root/include/host-shim")
"$cc" "${flags[@]}" "$source_file" \
"$kernel/portable/MemMang/heap_4.c" -o "$output"
else
"$cc" "${flags[@]}" "$source_file" -o "$output"
fi
objdump -dS "$output" > "$build_dir/prog.lst"
cp -f "$output" "$artifact_dir/prog"
copy_artifact "$build_dir/prog.lst"
printf '%s\n' "$output"
}
rv_env_root() {
if [[ -n "${RV_ENV_ROOT:-}" ]]; then
printf '%s\n' "$RV_ENV_ROOT"
elif [[ -f "$root/vendor/Hazard3/test/sim/common/init.S" && \
-f "$root/vendor/lab-runtime/memops.c" ]]; then
printf '%s\n' "$root"
elif [[ -d /opt/rv-env ]]; then
printf '%s\n' /opt/rv-env
else
printf '%s\n' /opt/stem
fi
}
build_hazard3() {
local env_root kernel build_dir elf
env_root="$(rv_env_root)"
kernel="$(freertos_kernel_path)"
verify_kernel "$kernel"
build_dir="$state/build/hazard3"
make -B -C "$root" "task$task_number" \
"BUILD_ROOT=$build_dir" "RV_ENV_ROOT=$env_root" \
"FREERTOS_KERNEL_PATH=$kernel" PROFILE=observe >&2 || return
elf="$build_dir/$task_stem/prog.elf"
test -s "$elf"
if [[ "$task_number" -eq 3 ]]; then
"$root/tests/check_task03_elf.sh" "$elf" >&2
fi
copy_artifact "$elf"
copy_artifact "${elf%.elf}.bin"
copy_artifact "${elf%.elf}.lst"
copy_artifact "${elf%.elf}.map"
printf '%s\n' "$elf"
}
hazard3_tb() {
local env_root tb
env_root="$(rv_env_root)"
tb="$env_root/vendor/Hazard3/test/sim/tb_verilator/tb"
if [[ ! -x "$tb" ]]; then
make -C "$(dirname -- "$tb")" tb >&2
fi
printf '%s\n' "$tb"
}
build_rp2350() {
local binary_type="${1:-no_flash}" build_kind build_dir elf kernel rp_kernel
local cmake_args
case "$binary_type" in
no_flash) build_kind=ram ;;
default) build_kind=flash ;;
*) printf 'Unsupported RP2350 binary type: %s\n' "$binary_type" >&2; return 2 ;;
esac
kernel="$(freertos_kernel_path)"
verify_kernel "$kernel"
rp_kernel="$(freertos_rp2350_path)"
verify_rp2350_kernel "$rp_kernel"
build_dir="$state/build/rp2350-rv-$build_kind"
cmake_args=(
-S "$root" -B "$build_dir"
-DPICO_PLATFORM=rp2350-riscv
-DPICO_BOARD="${PICO_BOARD:-pico2_w}"
-DPICO_GCC_TRIPLE=riscv32-pico-elf
-DHEAP4_UPSTREAM_ROOT="$kernel"
-DFREERTOS_RP2350_PATH="$rp_kernel"
-DHEAP4_PROFILE=observe
-DHEAP4_BINARY_TYPE="$binary_type"
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
)
if command -v ninja >/dev/null 2>&1; then
cmake_args+=(-G Ninja)
else
cmake_args+=(-G "Unix Makefiles")
fi
if [[ -d /opt/picotool/picotool ]]; then
cmake_args+=(-Dpicotool_DIR=/opt/picotool/picotool)
fi
cmake "${cmake_args[@]}" >&2
cmake --build "$build_dir" --target "$task_stem" >&2
elf="$build_dir/$task_stem.elf"
test -s "$elf"
riscv64-unknown-elf-objdump -dS -M no-aliases,numeric "$elf" \
> "$build_dir/$task_stem.lst"
copy_artifact "$elf"
copy_artifact "$build_dir/$task_stem.bin"
copy_artifact "$build_dir/$task_stem.hex"
copy_artifact "$build_dir/$task_stem.uf2"
copy_artifact "$build_dir/$task_stem.dis"
copy_artifact "$build_dir/$task_stem.lst"
copy_artifact "$build_dir/$task_stem.elf.map"
printf '%s\n' "$elf"
}
openocd_target="${STEM_OPENOCD_TARGET:-target/rp2350.cfg}"
gdb_port="${GDB_PORT:-3333}"
gdb_target="${GDB_TARGET:-127.0.0.1:$gdb_port}"
openocd_pid=""
stop_owned_openocd() {
if [[ -n "$openocd_pid" ]]; then
kill "$openocd_pid" 2>/dev/null || true
wait "$openocd_pid" 2>/dev/null || true
fi
}
start_openocd() {
local log="$state/openocd-rp2350.log" attempt
if nc -z 127.0.0.1 "$gdb_port" 2>/dev/null; then
return
fi
openocd -f interface/cmsis-dap.cfg \
-c "adapter speed ${STEM_ADAPTER_KHZ:-5000}" \
-c 'set USE_CORE { rv0 }' -c 'set USE_SMP 0' \
-c "set FLASHSIZE ${STEM_RP2350_FLASH_SIZE:-0x400000}" \
-f "$openocd_target" >"$log" 2>&1 &
openocd_pid=$!
for attempt in $(seq 1 80); do
if nc -z 127.0.0.1 "$gdb_port" 2>/dev/null; then
return
fi
if ! kill -0 "$openocd_pid" 2>/dev/null; then
sed -n '1,240p' "$log" >&2
return 1
fi
sleep 0.1
done
printf 'OpenOCD did not open GDB port %s\n' "$gdb_port" >&2
return 1
}
flash_rp2350() {
local elf="$1" log="$state/openocd-rp2350-flash.log"
if nc -z 127.0.0.1 "$gdb_port" 2>/dev/null; then
printf 'GDB port %s is busy; stop the current debug session before deploy.\n' "$gdb_port" >&2
return 1
fi
if ! openocd -f interface/cmsis-dap.cfg \
-c "adapter speed ${STEM_ADAPTER_KHZ:-5000}" \
-c 'set USE_CORE { cm0 rv0 }' -c 'set USE_SMP 0' \
-c "set FLASHSIZE ${STEM_RP2350_FLASH_SIZE:-0x400000}" \
-f "$openocd_target" -c init \
-c 'if {[target_present rp2350.rv0]} { targets rp2350.rv0 } else { targets rp2350.cm0 }' \
-c 'reset halt' -c "flash write_image erase $elf" \
-c "verify_image $elf" -c 'reset run' -c shutdown >"$log" 2>&1; then
sed -n '1,260p' "$log" >&2
return 1
fi
grep -E 'wrote [0-9]+ bytes|verified [0-9]+ bytes' "$log" || true
printf 'rp2350-flash-ok image=%s verify=passed architecture=RISC-V\n' "$elf"
}
hardware_test_task03() {
local elf="$1" output
start_openocd
trap stop_owned_openocd EXIT
output="$(gdb-multiarch -nx -q -batch "$elf" \
-ex 'set architecture riscv:rv32' \
-ex "target extended-remote $gdb_target" \
-ex 'monitor reset halt' \
-ex 'hbreak heap4_fragmented_checkpoint' \
-ex 'hbreak task03_debug_checkpoint' \
-ex continue \
-ex 'printf "fragmented blocks=%lu free=%lu largest=%lu\n", g_fragmented_stats.xNumberOfFreeBlocks, g_fragmented_stats.xAvailableHeapSpaceInBytes, g_fragmented_stats.xSizeOfLargestFreeBlockInBytes' \
-ex continue \
-ex 'printf "task03 initial=%lu after=%lu final=%lu min=%lu aligned=%d oom=%d hooks=%d asserts=%d pass=%d\n", g_initial_free, g_after_allocations, g_final_free, g_minimum_ever_free, g_allocations_aligned, g_oom_is_null, g_malloc_failed_hooks, g_assert_failures, g_task03_pass' \
-ex 'printf "frame sp=0x%08lx fp=0x%08lx pc=0x%08lx align=%lu\n", (unsigned long)$sp, (unsigned long)$s0, (unsigned long)$pc, ((unsigned long)$sp & 15)' \
-ex 'x/96bx ucHeap' \
-ex 'delete breakpoints' -ex 'monitor halt' -ex disconnect)"
printf '%s\n' "$output"
grep -E '^fragmented blocks=2 ' <<<"$output" >/dev/null
grep -E '^task03 .* aligned=1 oom=1 hooks=1 asserts=0 pass=1$' <<<"$output" >/dev/null
grep -E '^frame .* align=0$' <<<"$output" >/dev/null
printf 'rp2350-hardware-ok task=task03 heap_4=upstream load=flash\n'
}
configure_debug_view() {
export STEM_DEBUG_WINDOW_NAME=heap4
case "$task_number" in
1)
export STEM_DEBUG_INITIAL_BREAK=task01_debug_checkpoint
export STEM_DEBUG_MEMORY_EXPR='&g_split_arena' STEM_DEBUG_MEMORY_LENGTH=288
;;
2)
export STEM_DEBUG_INITIAL_BREAK=task02_fragmented_checkpoint
export STEM_DEBUG_MEMORY_EXPR='&g_coalesce_arena' STEM_DEBUG_MEMORY_LENGTH=160
;;
3)
export STEM_DEBUG_INITIAL_BREAK=heap4_reset_checkpoint
export STEM_DEBUG_MEMORY_EXPR='ucHeap' STEM_DEBUG_MEMORY_LENGTH=160
;;
esac
}
case "$profile:$target:$action" in
native-amd64:native:build)
build_native normal >/dev/null
;;
native-amd64:native:test)
output="$(build_native sanitizer)"
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 "$output"
;;
native-amd64:native:run)
output="$(build_native normal)"
exec "$output"
;;
native-amd64:native:debug)
output="$(build_native normal)"
export RV_REPO="$root" RV_EDITOR="${STEM_EDITOR:-nvim}"
export RV_HOST_ELF="$output" RV_HOST_SRC="$source_file"
export RV_HOST_LST="$(dirname -- "$output")/prog.lst"
exec /opt/stem/scripts/host-entry.sh debug "task$task_number"
;;
hazard3-sim:hazard3-baremetal:build)
build_hazard3 >/dev/null
;;
hazard3-sim:hazard3-baremetal:test|hazard3-sim:hazard3-baremetal:run)
elf="$(build_hazard3)"
tb="$(hazard3_tb)"
exec "$tb" --bin "${elf%.elf}.bin" --cpuret
;;
hazard3-sim:hazard3-baremetal:debug)
elf="$(build_hazard3)"
configure_debug_view
export STEM_DEBUG_BACKEND=hazard3 STEM_DEBUG_ELF="$elf"
export STEM_DEBUG_BIN="${elf%.elf}.bin" STEM_DEBUG_SRC="$source_file"
export STEM_DEBUG_LST="${elf%.elf}.lst"
exec /opt/stem/scripts/card-debug-ui.sh
;;
rp2350:rp2350-rv:build)
build_rp2350 >/dev/null
;;
rp2350:rp2350-rv:test)
elf="$(build_rp2350)"
riscv64-unknown-elf-readelf -h "$elf" | grep -F 'Machine:' | grep -F 'RISC-V'
if [[ "$task_number" -eq 3 ]]; then
"$root/tests/check_task03_elf.sh" "$elf"
fi
printf 'rp2350-build-ok task=%s binary_type=no_flash\n' "$task_key"
;;
rp2350:rp2350-rv:deploy)
elf="$(build_rp2350 default)"
flash_rp2350 "$elf"
if [[ "$task_number" -eq 3 ]]; then
hardware_test_task03 "$elf"
else
printf 'rp2350-deploy-ok task=%s load=flash persistent=1\n' "$task_key"
fi
;;
rp2350:rp2350-rv:debug)
elf="$(build_rp2350)"
configure_debug_view
export STEM_DEBUG_BACKEND=rp2350 STEM_DEBUG_ELF="$elf"
export STEM_DEBUG_SRC="$source_file" STEM_DEBUG_LST="${elf%.elf}.lst"
exec /opt/stem/scripts/card-debug-ui.sh
;;
*)
printf 'Unsupported profile/target/action: %s/%s/%s\n' "$profile" "$target" "$action" >&2
exit 2
;;
esac
+1
View File
File diff suppressed because one or more lines are too long
+61
View File
File diff suppressed because one or more lines are too long
+4431
View File
File diff suppressed because one or more lines are too long
+31
View File
@@ -0,0 +1,31 @@
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A1 CONTEXT — from linear cursor to reusable heap
rectangle "<<application>>\n01 A / B / C experiment\nrequests payload bytes" as APP
rectangle "<<public API>>\n02 pvPortMalloc / vPortFree\nheap statistics" as API
rectangle "<<allocator>>\n03 heap_4\nfirst-fit · split · coalesce" as H4
rectangle "<<arena>>\n04 ucHeap[4096]\nheaders + payload" as ARENA
rectangle "<<target>>\n05 Hazard3 / RV32I\nGDB · registers · memory" as TARGET
APP -down-> API : request / release
API -down-> H4 : direct C call
H4 -down-> ARENA : manages
ARENA -down-> TARGET : stored in RAM
note right of H4
heap_1: allocate only
heap_2: free, no coalesce
heap_3: libc wrapper
heap_4: free + coalesce
heap_5: multiple regions
end note
@enduml
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="600.3488px" preserveAspectRatio="none" style="width:311px;height:600px;" version="1.1" viewBox="0 0 311 600" width="311.19px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="227.6552" x="44.9803" y="9.813">A1 CONTEXT — from linear cursor to reusable heap</text><!--MD5=[cd187d11655e4367e900de538d2f1d0c]
entity APP--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="121.1713" x="15.6054" y="20.2686"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="58.7497" x="24.785" y="39.2613">«application»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="102.812" x="24.785" y="51.764">01 A / B / C experiment</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="102.812" x="24.785" y="64.2667">requests payload bytes</text><!--MD5=[645d8587175d8f7ad110cd370775931d]
entity API--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="141.3665" x="5.5078" y="144.9833"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="52.324" x="14.6874" y="163.976">«public API»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="123.0073" x="14.6874" y="176.4787">02 pvPortMalloc / vPortFree</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="65.1755" x="14.6874" y="188.9813">heap statistics</text><!--MD5=[46e692d45a0b60d87b097c4043ce42a2]
entity H4--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="122.0893" x="15.1464" y="277.6108"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="48.6521" x="24.3261" y="296.6035">«allocator»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="44.9803" x="24.3261" y="309.1062">03 heap_4</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="103.73" x="24.3261" y="321.6088">first-fit · split · coalesce</text><!--MD5=[a55d5013c595d66e4d3c908e0eed28a7]
entity ARENA--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="100.0581" x="26.162" y="410.2384"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="34.8827" x="35.3416" y="429.231">«arena»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="74.3551" x="35.3416" y="441.7337">04 ucHeap[4096]</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="81.6988" x="35.3416" y="454.2364">headers + payload</text><!--MD5=[aba7613092619c8a5fef3de1c87efe89]
entity TARGET--><rect fill="#EDF6FA" height="55.8673" style="stroke: #2C7794; stroke-width: 1.3769468762104042;" width="129.433" x="11.4746" y="534.953"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="36.7186" x="20.6542" y="553.9457">«target»</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="84.4527" x="20.6542" y="566.4484">05 Hazard3 / RV32I</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="111.0737" x="20.6542" y="578.951">GDB · registers · memory</text><path d="M169.3645,269.698 L169.3645,301.8726 L137.6029,305.5445 L169.3645,309.2164 L169.3645,341.391 A0,0 0 0 0 169.3645,341.391 L300.6334,341.391 A0,0 0 0 0 300.6334,341.391 L300.6334,278.8776 L291.4538,269.698 L169.3645,269.698 A0,0 0 0 0 169.3645,269.698 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.9179645841402695;"/><path d="M291.4538,269.698 L291.4538,278.8776 L300.6334,278.8776 L291.4538,269.698 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="93.6324" x="174.8723" y="284.1008">heap_1: allocate only</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="111.9917" x="174.8723" y="296.6035">heap_2: free, no coalesce</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="91.7965" x="174.8723" y="309.1062">heap_3: libc wrapper</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="103.73" x="174.8723" y="321.6088">heap_4: free + coalesce</text><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="109.2378" x="174.8723" y="334.1115">heap_5: multiple regions</text><!--MD5=[ec942d3abfeef98a0155e2f031d4c131]
link APP to API--><path d="M76.1911,76.393 C76.1911,94.8441 76.1911,119.3262 76.1911,138.8972 " fill="none" id="APP-&gt;API" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,143.4136,79.8629,135.1519,76.1911,138.8238,72.5192,135.1519,76.1911,143.4136" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="76.1911" x="77.109" y="114.4059">request / release</text><!--MD5=[798ded9ffd9ac635cdedeacba358c97c]
link API to H4--><path d="M76.1911,201.2545 C76.1911,221.6609 76.1911,249.6129 76.1911,271.3044 " fill="none" id="API-&gt;H4" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,275.8575,79.8629,267.5958,76.1911,271.2677,72.5192,267.5958,76.1911,275.8575" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="52.324" x="77.109" y="239.1206">direct C call</text><!--MD5=[26d2234bc3ca60bb174d49bba6317b2c]
link H4 to ARENA--><path d="M76.1911,333.8821 C76.1911,354.2884 76.1911,382.2404 76.1911,403.9319 " fill="none" id="H4-&gt;ARENA" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,408.485,79.8629,400.2234,76.1911,403.8952,72.5192,400.2234,76.1911,408.485" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="40.3904" x="77.109" y="379.661">manages</text><!--MD5=[057090cc36f41caea0c560281f72f0d5]
link ARENA to TARGET--><path d="M76.1911,466.3627 C76.1911,484.8138 76.1911,509.2959 76.1911,528.8669 " fill="none" id="ARENA-&gt;TARGET" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><polygon fill="#8095A1" points="76.1911,533.3833,79.8629,525.1216,76.1911,528.7935,72.5192,525.1216,76.1911,533.3833" style="stroke: #8095A1; stroke-width: 0.9179645841402695;"/><text fill="#000000" font-family="Monospace" font-size="9.1796" lengthAdjust="spacingAndGlyphs" textLength="61.5036" x="77.109" y="504.3756">stored in RAM</text><!--MD5=[5f927a6771e8d55dac04e3c75dd184e1]
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A1 CONTEXT — from linear cursor to reusable heap
rectangle "<<application>>\n01 A / B / C experiment\nrequests payload bytes" as APP
rectangle "<<public API>>\n02 pvPortMalloc / vPortFree\nheap statistics" as API
rectangle "<<allocator>>\n03 heap_4\nfirst-fit · split · coalesce" as H4
rectangle "<<arena>>\n04 ucHeap[4096]\nheaders + payload" as ARENA
rectangle "<<target>>\n05 Hazard3 / RV32I\nGDB · registers · memory" as TARGET
APP -down-> API : request / release
API -down-> H4 : direct C call
H4 -down-> ARENA : manages
ARENA -down-> TARGET : stored in RAM
note right of H4
heap_1: allocate only
heap_2: free, no coalesce
heap_3: libc wrapper
heap_4: free + coalesce
heap_5: multiple regions
end note
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

+53
View File
@@ -0,0 +1,53 @@
@startuml
scale 620 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam classBorderColor #2c7794
skinparam classBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A2 STRUCTURE — RV32 header, split and two-sided coalescing
class "01 Block header" as HEADER {
next : BlockLink_t*
size : size_t
raw sizeof = 8 bytes on RV32
aligned xHeapStructSize = 16
}
class "Allocated block" as ALLOC {
02 A: header + 24 byte request
aligned total = 48 bytes
payload begins after header
}
class "03 Free remainder" as REM {
own header
free = 4032 bytes after A
}
HEADER *-- ALLOC : precedes payload
ALLOC -down-> REM : first-fit + split
class "04 Address-ordered free list" as LIST {
previous < inserted < current
A < B < C+tail
}
class "05 Previous / left neighbour" as LEFT {
previous + previous.size == inserted
merge previous first
}
class "06 Next / right neighbour" as RIGHT {
merged + merged.size == current
merge next second
}
REM -down-> LIST : insert by address
LIST -down-> LEFT : heap_4 tests first
LEFT -down-> RIGHT : then tests next
note right of LIST
Address order exposes both physical
neighbours without scanning the arena.
end note
@enduml
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="620.2694px" preserveAspectRatio="none" style="width:312px;height:620px;" version="1.1" viewBox="0 0 312 620" width="312.6158px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="211.9549" x="52.4571" y="7.5779">A2 STRUCTURE — RV32 header, split and two-sided coalescing</text><!--MD5=[9827fb78ff6e3f59cfadf959dc26af7c]
class HEADER--><rect fill="#EDF6FA" height="69.8104" id="HEADER" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="107.7497" x="16.3042" y="15.1133"/><ellipse cx="40.1935" cy="25.0376" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M41.1017,27.3747 Q40.858,27.4965 40.5922,27.5519 Q40.3264,27.6184 40.0273,27.6184 Q38.9861,27.6184 38.4323,26.9316 Q37.8896,26.2449 37.8896,24.9379 Q37.8896,23.6309 38.4323,22.9442 Q38.9861,22.2575 40.0273,22.2575 Q40.3264,22.2575 40.5922,22.3239 Q40.8691,22.3793 41.1017,22.5011 L41.1017,23.642 Q40.8359,23.3983 40.5811,23.2876 Q40.3374,23.1768 40.0827,23.1768 Q39.5178,23.1768 39.2298,23.6198 Q38.9418,24.0629 38.9418,24.9379 Q38.9418,25.8129 39.2298,26.256 Q39.5178,26.699 40.0827,26.699 Q40.3374,26.699 40.5811,26.5883 Q40.8359,26.4775 41.1017,26.2338 L41.1017,27.3747 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="55.2926" x="51.9609" y="27.7881">01 Block header</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="17.0131" x2="123.345" y1="34.9619" y2="34.9619"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="63.0903" x="20.5575" y="45.3753">next : BlockLink_t*</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="38.9884" x="20.5575" y="55.0303">size : size_t</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="97.8253" x="20.5575" y="64.6852">raw sizeof = 8 bytes on RV32</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="99.2431" x="20.5575" y="74.3401">aligned xHeapStructSize = 16</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="17.0131" x2="123.345" y1="79.2527" y2="79.2527"/><!--MD5=[40d637119be40bcfdc4ce848efbdda9e]
class ALLOC--><rect fill="#EDF6FA" height="60.1555" id="ALLOC" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="114.1296" x="13.1143" y="138.0897"/><ellipse cx="41.6467" cy="148.014" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M42.5549,150.3511 Q42.3112,150.4729 42.0454,150.5283 Q41.7796,150.5948 41.4805,150.5948 Q40.4393,150.5948 39.8855,149.908 Q39.3428,149.2213 39.3428,147.9143 Q39.3428,146.6073 39.8855,145.9206 Q40.4393,145.2339 41.4805,145.2339 Q41.7796,145.2339 42.0454,145.3003 Q42.3223,145.3557 42.5549,145.4775 L42.5549,146.6184 Q42.2891,146.3747 42.0343,146.2639 Q41.7906,146.1532 41.5359,146.1532 Q40.971,146.1532 40.683,146.5962 Q40.395,147.0393 40.395,147.9143 Q40.395,148.7893 40.683,149.2324 Q40.971,149.6754 41.5359,149.6754 Q41.7906,149.6754 42.0343,149.5647 Q42.2891,149.4539 42.5549,149.2102 L42.5549,150.3511 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="51.7482" x="54.052" y="150.7644">Allocated block</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.8231" x2="126.535" y1="157.9383" y2="157.9383"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="105.623" x="17.3675" y="168.3517">02 A: header + 24 byte request</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="81.5211" x="17.3675" y="178.0067">aligned total = 48 bytes</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="96.4076" x="17.3675" y="187.6616">payload begins after header</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.8231" x2="126.535" y1="192.5741" y2="192.5741"/><!--MD5=[71c2adef9be32489055f250a531e7c6f]
class REM--><rect fill="#EDF6FA" height="50.5005" id="REM" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="92.8632" x="23.7475" y="251.4111"/><ellipse cx="37.4288" cy="261.3354" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M38.3371,263.6725 Q38.0934,263.7944 37.8276,263.8497 Q37.5617,263.9162 37.2627,263.9162 Q36.2215,263.9162 35.6677,263.2295 Q35.125,262.5427 35.125,261.2357 Q35.125,259.9287 35.6677,259.242 Q36.2215,258.5553 37.2627,258.5553 Q37.5617,258.5553 37.8276,258.6218 Q38.1045,258.6771 38.3371,258.799 L38.3371,259.9398 Q38.0712,259.6961 37.8165,259.5854 Q37.5728,259.4746 37.3181,259.4746 Q36.7532,259.4746 36.4652,259.9177 Q36.1772,260.3607 36.1772,261.2357 Q36.1772,262.1108 36.4652,262.5538 Q36.7532,262.9969 37.3181,262.9969 Q37.5728,262.9969 37.8165,262.8861 Q38.0712,262.7753 38.3371,262.5317 L38.3371,263.6725 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="63.0903" x="46.9278" y="264.0859">03 Free remainder</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="24.4563" x2="115.9018" y1="271.2597" y2="271.2597"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="40.4061" x="28.0007" y="281.6732">own header</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="84.3566" x="28.0007" y="291.3281">free = 4032 bytes after A</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="24.4563" x2="115.9018" y1="296.2406" y2="296.2406"/><!--MD5=[b0a0edd67d9eafaaa5639bbe6382adce]
class LIST--><rect fill="#EDF6FA" height="50.5005" id="LIST" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="114.8384" x="12.7598" y="355.0776"/><ellipse cx="21.9753" cy="365.0019" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M22.8835,367.339 Q22.6398,367.4609 22.374,367.5162 Q22.1082,367.5827 21.8091,367.5827 Q20.7679,367.5827 20.2141,366.896 Q19.6714,366.2093 19.6714,364.9023 Q19.6714,363.5953 20.2141,362.9085 Q20.7679,362.2218 21.8091,362.2218 Q22.1082,362.2218 22.374,362.2883 Q22.6509,362.3436 22.8835,362.4655 L22.8835,363.6063 Q22.6177,363.3627 22.3629,363.2519 Q22.1192,363.1411 21.8645,363.1411 Q21.2996,363.1411 21.0116,363.5842 Q20.7236,364.0272 20.7236,364.9023 Q20.7236,365.7773 21.0116,366.2203 Q21.2996,366.6634 21.8645,366.6634 Q22.1192,366.6634 22.3629,366.5526 Q22.6177,366.4419 22.8835,366.1982 L22.8835,367.339 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="94.9898" x="30.4818" y="367.7524">04 Address-ordered free list</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.4687" x2="126.8894" y1="374.9263" y2="374.9263"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="99.2431" x="17.0131" y="385.3397">previous &lt; inserted &lt; current</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="46.0772" x="17.0131" y="394.9946">A &lt; B &lt; C+tail</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="13.4687" x2="126.8894" y1="399.9071" y2="399.9071"/><!--MD5=[007d3a1820cefd008c8dbdad7e6fdec6]
class LEFT--><rect fill="#EDF6FA" height="50.5005" id="LEFT" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="131.8515" x="4.2533" y="458.7441"/><ellipse cx="21.1246" cy="468.6684" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M22.0329,471.0055 Q21.7892,471.1274 21.5233,471.1828 Q21.2575,471.2492 20.9585,471.2492 Q19.9173,471.2492 19.3635,470.5625 Q18.8207,469.8758 18.8207,468.5688 Q18.8207,467.2618 19.3635,466.575 Q19.9173,465.8883 20.9585,465.8883 Q21.2575,465.8883 21.5233,465.9548 Q21.8003,466.0102 22.0329,466.132 L22.0329,467.2728 Q21.767,467.0292 21.5123,466.9184 Q21.2686,466.8076 21.0138,466.8076 Q20.449,466.8076 20.161,467.2507 Q19.873,467.6937 19.873,468.5688 Q19.873,469.4438 20.161,469.8868 Q20.449,470.3299 21.0138,470.3299 Q21.2686,470.3299 21.5123,470.2191 Q21.767,470.1084 22.0329,469.8647 L22.0329,471.0055 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="94.9898" x="31.3325" y="471.4189">05 Previous / left neighbour</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="4.9622" x2="135.3959" y1="478.5928" y2="478.5928"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="123.345" x="8.5066" y="489.0062">previous + previous.size == inserted</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="68.7613" x="8.5066" y="498.6611">merge previous first</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="4.9622" x2="135.3959" y1="503.5736" y2="503.5736"/><!--MD5=[490fcd32b6546c9bc615869efabd094a]
class RIGHT--><rect fill="#EDF6FA" height="50.5005" id="RIGHT" style="stroke: #2C7794; stroke-width: 1.0633189422886131;" width="122.6361" x="8.861" y="562.4106"/><ellipse cx="25.0943" cy="572.335" fill="#ADD1B2" rx="6.3799" ry="6.3799" style="stroke: #2C7794; stroke-width: 0.7088792948590754;"/><path d="M26.0026,574.672 Q25.7589,574.7939 25.4931,574.8493 Q25.2272,574.9157 24.9282,574.9157 Q23.887,574.9157 23.3332,574.229 Q22.7905,573.5423 22.7905,572.2353 Q22.7905,570.9283 23.3332,570.2415 Q23.887,569.5548 24.9282,569.5548 Q25.2272,569.5548 25.4931,569.6213 Q25.77,569.6767 26.0026,569.7985 L26.0026,570.9394 Q25.7367,570.6957 25.482,570.5849 Q25.2383,570.4741 24.9836,570.4741 Q24.4187,570.4741 24.1307,570.9172 Q23.8427,571.3602 23.8427,572.2353 Q23.8427,573.1103 24.1307,573.5533 Q24.4187,573.9964 24.9836,573.9964 Q25.2383,573.9964 25.482,573.8856 Q25.7367,573.7749 26.0026,573.5312 L26.0026,574.672 Z "/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="87.1922" x="35.1604" y="575.0854">06 Next / right neighbour</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="9.5699" x2="130.7882" y1="582.2593" y2="582.2593"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="114.1296" x="13.1143" y="592.6727">merged + merged.size == current</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="65.2169" x="13.1143" y="602.3276">merge next second</text><line style="stroke: #2C7794; stroke-width: 1.0633189422886131;" x1="9.5699" x2="130.7882" y1="607.2402" y2="607.2402"/><path d="M152.409,367.1286 L152.409,377.4924 L127.9173,380.3279 L152.409,383.1634 L152.409,393.5272 A0,0 0 0 0 152.409,393.5272 L304.1092,393.5272 A0,0 0 0 0 304.1092,393.5272 L304.1092,374.2174 L297.0204,367.1286 L152.409,367.1286 A0,0 0 0 0 152.409,367.1286 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7088792948590754;"/><path d="M297.0204,367.1286 L297.0204,374.2174 L304.1092,374.2174 L297.0204,367.1286 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="124.7628" x="156.6623" y="378.2509">Address order exposes both physical</text><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="136.8137" x="156.6623" y="387.9058">neighbours without scanning the arena.</text><!--MD5=[fc2657b7de304bb41a5d36ac60748945]
reverse link HEADER to ALLOC--><path d="M70.1791,95.245 C70.1791,109.5006 70.1791,124.9329 70.1791,137.8557 " fill="none" id="HEADER&lt;-ALLOC" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,86.1926,67.3435,90.4459,70.1791,94.6992,73.0146,90.4459,70.1791,86.1926" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="60.2547" x="70.8879" y="114.4769">precedes payload</text><!--MD5=[bb73b5a7e21afff1a1d0c43dcbd5d11a]
link ALLOC to REM--><path d="M70.1791,198.4224 C70.1791,213.4506 70.1791,231.6688 70.1791,246.6687 " fill="none" id="ALLOC-&gt;REM" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,250.1422,73.0146,243.7623,70.1791,246.5978,67.3435,243.7623,70.1791,250.1422" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="46.0772" x="70.8879" y="227.7983">first-fit + split</text><!--MD5=[32aec76f28e14f88b0d74d9f592c80fb]
link REM to LIST--><path d="M70.1791,302.1243 C70.1791,316.5855 70.1791,334.9242 70.1791,350.1297 " fill="none" id="REM-&gt;LIST" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,353.667,73.0146,347.287,70.1791,350.1226,67.3435,347.287,70.1791,353.667" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="58.837" x="70.8879" y="331.4649">insert by address</text><!--MD5=[cc3605e5f4ba919f564e1d79e1300518]
link LIST to LEFT--><path d="M70.1791,405.7909 C70.1791,420.252 70.1791,438.5907 70.1791,453.7962 " fill="none" id="LIST-&gt;LEFT" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,457.3335,73.0146,450.9536,70.1791,453.7891,67.3435,450.9536,70.1791,457.3335" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="58.837" x="70.8879" y="435.1314">heap_4 tests first</text><!--MD5=[e8df39c6ef374d140d6cfa6fe0b5ac87]
link LEFT to RIGHT--><path d="M70.1791,509.4574 C70.1791,523.9185 70.1791,542.2572 70.1791,557.4627 " fill="none" id="LEFT-&gt;RIGHT" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><polygon fill="#8095A1" points="70.1791,561,73.0146,554.6201,70.1791,557.4556,67.3435,554.6201,70.1791,561" style="stroke: #8095A1; stroke-width: 0.7088792948590754;"/><text fill="#000000" font-family="Monospace" font-size="7.0888" lengthAdjust="spacingAndGlyphs" textLength="51.7482" x="70.8879" y="538.7979">then tests next</text><!--MD5=[d8b34fb36bd2f73cd895320cbfc22e63]
@startuml
scale 620 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam classBorderColor #2c7794
skinparam classBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A2 STRUCTURE — RV32 header, split and two-sided coalescing
class "01 Block header" as HEADER {
next : BlockLink_t*
size : size_t
raw sizeof = 8 bytes on RV32
aligned xHeapStructSize = 16
}
class "Allocated block" as ALLOC {
02 A: header + 24 byte request
aligned total = 48 bytes
payload begins after header
}
class "03 Free remainder" as REM {
own header
free = 4032 bytes after A
}
HEADER *- - ALLOC : precedes payload
ALLOC -down-> REM : first-fit + split
class "04 Address-ordered free list" as LIST {
previous < inserted < current
A < B < C+tail
}
class "05 Previous / left neighbour" as LEFT {
previous + previous.size == inserted
merge previous first
}
class "06 Next / right neighbour" as RIGHT {
merged + merged.size == current
merge next second
}
REM -down-> LIST : insert by address
LIST -down-> LEFT : heap_4 tests first
LEFT -down-> RIGHT : then tests next
note right of LIST
Address order exposes both physical
neighbours without scanning the arena.
end note
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 16 KiB

+29
View File
@@ -0,0 +1,29 @@
@startuml
scale 820 width
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A5 FLOW — eight deterministic Hazard3 replay states
rectangle "01 E01 RESET\n1 block · free=4080\nraw header=8 · aligned=16" as S1
rectangle "02 E02 ALLOC A(24)\nconsumed=48\nfree=4032" as S2
rectangle "03 E03 ALLOC B(40)\nconsumed=64\nfree=3968" as S3
rectangle "04 E04 ALLOC C(16)\nconsumed=32\nfree=3936" as S4
rectangle "05 E05 FREE A\n2 free blocks\nfree=3984" as S5
rectangle "06 E06 FREE C\n2 blocks · fragmented\nfree=4016" as S6
rectangle "07 E07 FREE B\nmerge left + right\n1 block · free=4080" as S7
rectangle "08 E08 OOM / VERIFY\nNULL · hook=1\nasserts=0 · PASS=1" as S8
S1 -right-> S2 : pvPortMalloc
S2 -right-> S3 : split remainder
S3 -right-> S4 : split remainder
S4 -down-> S5 : vPortFree(A)
S5 -left-> S6 : vPortFree(C)
S6 -left-> S7 : vPortFree(B)
S7 -left-> S8 : oversized request
@enduml
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="236.6008px" preserveAspectRatio="none" style="width:812px;height:236px;" version="1.1" viewBox="0 0 812 236" width="812.4374px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="239.8419" x="290.0791" y="10.3943">A5 FLOW — eight deterministic Hazard3 replay states</text><!--MD5=[d0cae5ff9305becd6f502d4fe4f41481]
entity S1--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="142.6087" x="6.4822" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="59.4203" x="17.2859" y="43.5704">01 E01 RESET</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="83.1884" x="17.2859" y="56.8136">1 block · free=4080</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="121.0013" x="17.2859" y="70.0569">raw header=8 · aligned=16</text><!--MD5=[d3395af3100fe8cebf35265100c4415f]
entity S2--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="110.1976" x="247.4045" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="88.5903" x="258.2082" y="43.5704">02 E02 ALLOC A(24)</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="63.7418" x="258.2082" y="56.8136">consumed=48</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="258.2082" y="70.0569">free=4032</text><!--MD5=[6c7192638421eaf134d201765ac5db29]
entity S3--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="110.1976" x="466.7194" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="88.5903" x="477.5231" y="43.5704">03 E03 ALLOC B(40)</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="63.7418" x="477.5231" y="56.8136">consumed=64</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="477.5231" y="70.0569">free=3968</text><!--MD5=[01b905ebe31ca24275b86a9951c478d0]
entity S4--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="110.1976" x="686.0343" y="22.3724"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="88.5903" x="696.8379" y="43.5704">04 E04 ALLOC C(16)</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="63.7418" x="696.8379" y="56.8136">consumed=32</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="696.8379" y="70.0569">free=3936</text><!--MD5=[099bd2cf1f4f3a6dbf2f1fde6174f38e]
entity S5--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="84.2688" x="698.9987" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="62.6614" x="709.8024" y="184.861">05 E05 FREE A</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="56.1792" x="709.8024" y="198.1043">2 free blocks</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="709.8024" y="211.3475">free=3984</text><!--MD5=[0656c7721b015b9ca8cf2e2c2e8f5aee]
entity S6--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="118.8406" x="484.0053" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="62.6614" x="494.809" y="184.861">06 E06 FREE C</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="97.2332" x="494.809" y="198.1043">2 blocks · fragmented</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="45.3755" x="494.809" y="211.3475">free=4016</text><!--MD5=[6ba532df225878998c5769132c3837e2]
entity S7--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="104.7958" x="282.5165" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="62.6614" x="293.3202" y="184.861">07 E07 FREE B</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="78.8669" x="293.3202" y="198.1043">merge left + right</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="83.1884" x="293.3202" y="211.3475">1 block · free=4080</text><!--MD5=[ce611cd767df6ac8a45071985dabb378]
entity S8--><rect fill="#EDF6FA" height="61.3371" style="stroke: #2C7794; stroke-width: 1.6205533596837944;" width="115.5995" x="46.996" y="163.663"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="93.9921" x="57.7997" y="184.861">08 E08 OOM / VERIFY</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="65.9025" x="57.7997" y="198.1043">NULL · hook=1</text><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="82.108" x="57.7997" y="211.3475">asserts=0 · PASS=1</text><!--MD5=[15cb110786dd224ca6a510a3d2a24e20]
link S1 to S2--><path d="M149.5014,53.044 C178.639,53.044 211.9792,53.044 240.0796,53.044 " fill="none" id="S1-&gt;S2" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="245.4706,53.044,235.7473,48.7226,240.0688,53.044,235.7473,57.3655,245.4706,53.044" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="58.3399" x="169.0777" y="46.1524">pvPortMalloc</text><!--MD5=[8eac89d31ced3c9003fbd6a8a005c745]
link S2 to S3--><path d="M358.1315,53.044 C389.0516,53.044 427.6208,53.044 459.5457,53.044 " fill="none" id="S2-&gt;S3" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="464.6126,53.044,454.8893,48.7226,459.2108,53.044,454.8893,57.3655,464.6126,53.044" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="69.1436" x="377.5889" y="46.1524">split remainder</text><!--MD5=[82e284a09e4ebade00512bdc77bff32c]
link S3 to S4--><path d="M577.4464,53.044 C608.3665,53.044 646.9357,53.044 678.8606,53.044 " fill="none" id="S3-&gt;S4" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="683.9275,53.044,674.2042,48.7226,678.5257,53.044,674.2042,57.3655,683.9275,53.044" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="69.1436" x="596.9038" y="46.1524">split remainder</text><!--MD5=[0e6b031b378ab8978eaa734a548bdfb6]
link S4 to S5--><path d="M741.1331,83.9642 C741.1331,105.2367 741.1331,133.9637 741.1331,156.6298 " fill="none" id="S4-&gt;S5" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="741.1331,161.8156,745.4545,152.0923,741.1331,156.4137,736.8116,152.0923,741.1331,161.8156" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="57.2596" x="742.2134" y="127.6015">vPortFree(A)</text><!--MD5=[3c9aaad44b43c509ca535c241fdd0151]
reverse link S6 to S5--><path d="M610.2356,194.3239 C639.492,194.3239 672.9618,194.3239 698.7286,194.3239 " fill="none" id="S6&lt;-S5" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="604.9202,194.3239,614.6435,198.6454,610.322,194.3239,614.6435,190.0024,604.9202,194.3239" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="57.2596" x="622.2925" y="187.4323">vPortFree(C)</text><!--MD5=[5f6ea4567bb0950bff1d27387d49b4c2]
reverse link S7 to S6--><path d="M394.7668,194.3239 C422.6403,194.3239 455.7212,194.3239 483.5947,194.3239 " fill="none" id="S7&lt;-S6" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="389.4406,194.3239,399.1639,198.6454,394.8424,194.3239,399.1639,190.0024,389.4406,194.3239" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="57.2596" x="407.029" y="187.4323">vPortFree(B)</text><!--MD5=[630b9631f886cf9c8b0d992525b86cf3]
reverse link S8 to S7--><path d="M169.8448,194.3239 C205.3025,194.3239 248.6253,194.3239 281.9871,194.3239 " fill="none" id="S8&lt;-S7" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><polygon fill="#8095A1" points="164.497,194.3239,174.2203,198.6454,169.8988,194.3239,174.2203,190.0024,164.497,194.3239" style="stroke: #8095A1; stroke-width: 1.080368906455863;"/><text fill="#000000" font-family="Monospace" font-size="9.7233" lengthAdjust="spacingAndGlyphs" textLength="81.0277" x="182.0422" y="187.4323">oversized request</text><!--MD5=[9f7e06700e17220ce72e8c57ed6bc819]
@startuml
scale 820 width
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A5 FLOW — eight deterministic Hazard3 replay states
rectangle "01 E01 RESET\n1 block · free=4080\nraw header=8 · aligned=16" as S1
rectangle "02 E02 ALLOC A(24)\nconsumed=48\nfree=4032" as S2
rectangle "03 E03 ALLOC B(40)\nconsumed=64\nfree=3968" as S3
rectangle "04 E04 ALLOC C(16)\nconsumed=32\nfree=3936" as S4
rectangle "05 E05 FREE A\n2 free blocks\nfree=3984" as S5
rectangle "06 E06 FREE C\n2 blocks · fragmented\nfree=4016" as S6
rectangle "07 E07 FREE B\nmerge left + right\n1 block · free=4080" as S7
rectangle "08 E08 OOM / VERIFY\nNULL · hook=1\nasserts=0 · PASS=1" as S8
S1 -right-> S2 : pvPortMalloc
S2 -right-> S3 : split remainder
S3 -right-> S4 : split remainder
S4 -down-> S5 : vPortFree(A)
S5 -left-> S6 : vPortFree(C)
S6 -left-> S7 : vPortFree(B)
S7 -left-> S8 : oversized request
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 11 KiB

+29
View File
@@ -0,0 +1,29 @@
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam stateBorderColor #2c7794
skinparam stateBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A6 STATE — reusable states of the same RV32 arena
[*] --> Free : 01 E01 one list node
Free --> Allocated : 02 E04 A+B+C allocated\ncurrent free = 3936
Allocated --> Fragmented : E05 free A\nE06 free C
Fragmented : 03 E06 two free blocks
Fragmented : sum free > largest block
Fragmented --> Coalesced : 04 E07 free B\nmerge previous, then next
Coalesced : one free block
Coalesced : current = largest = initial
Coalesced --> OOMChecked : 05 E08 request > arena
OOMChecked : NULL · hook=1 · PASS=1
OOMChecked --> [*]
state "minimum-ever" as MIN
Allocated -right-> MIN : records low watermark
Fragmented -right-> MIN : does not rise
Coalesced -right-> MIN : history remains
@enduml
+50
View File
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="600.2775px" preserveAspectRatio="none" style="width:321px;height:600px;" version="1.1" viewBox="0 0 321 600" width="321.3164px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="184.7569" x="70.8357" y="7.8065">A6 STATE — reusable states of the same RV32 arena</text><ellipse cx="193.155" cy="23.2954" fill="#000000" rx="7.3026" ry="7.3026" style="stroke: none; stroke-width: 0.7302646103274287;"/><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="36.5132" x="174.8984" y="85.3679"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="174.8984" x2="211.4116" y1="102.6168" y2="102.6168"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="15.3356" x="185.4872" y="96.8258">Free</text><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="47.4672" x="169.4214" y="186.8747"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="169.4214" x2="216.8886" y1="204.1235" y2="204.1235"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="32.8619" x="176.724" y="198.3325">Allocated</text><rect fill="#EDF6FA" height="44.4439" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="99.316" x="93.1087" y="288.3815"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="93.1087" x2="192.4247" y1="305.6303" y2="305.6303"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="42.3553" x="121.5891" y="299.8393">Fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="79.5988" x="96.7601" y="317.0882">03 E06 two free blocks</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="84.7107" x="96.7601" y="327.0344">sum free &gt; largest block</text><rect fill="#EDF6FA" height="44.4439" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="102.9673" x="4.3816" y="397.8189"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="4.3816" x2="107.3489" y1="415.0678" y2="415.0678"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="35.783" x="37.9738" y="409.2768">Coalesced</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="49.658" x="8.0329" y="426.5256">one free block</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="88.362" x="8.0329" y="436.4718">current = largest = initial</text><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="96.3949" x="7.6678" y="497.0327"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="7.6678" x2="104.0627" y1="514.2815" y2="514.2815"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="47.4672" x="32.1316" y="508.4905">OOMChecked</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="81.7896" x="11.3191" y="525.7394">NULL · hook=1 · PASS=1</text><ellipse cx="55.8652" cy="585.3947" fill="none" rx="7.3026" ry="7.3026" style="stroke: #000000; stroke-width: 0.7302646103274287;"/><ellipse cx="56.2304" cy="585.7598" fill="#000000" rx="4.3816" ry="4.3816" style="stroke: none; stroke-width: 0.7302646103274287;"/><rect fill="#EDF6FA" height="36.5132" rx="9.1283" ry="9.1283" style="stroke: #2C7794; stroke-width: 1.0953969154911432;" width="64.9936" x="188.4083" y="401.7843"/><line style="stroke: #2C7794; stroke-width: 1.0953969154911432;" x1="188.4083" x2="253.4018" y1="419.0331" y2="419.0331"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="50.3883" x="195.7109" y="413.2421">minimum-ever</text><!--MD5=[f16808fa220dde377303612249059854]
link *start to Free--><path d="M193.155,30.7514 C193.155,41.647 193.155,63.6352 193.155,80.4898 " fill="none" id="*start-&gt;Free" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="193.155,83.9877,196.076,77.4153,193.155,80.3364,190.2339,77.4153,193.155,83.9877" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="72.2962" x="193.8853" y="61.0428">01 E01 one list node</text><!--MD5=[19abaf48dc778410378e95e0d1bca006]
link Free to Allocated--><path d="M193.155,122.239 C193.155,138.9547 193.155,163.9809 193.155,182.0111 " fill="none" id="Free-&gt;Allocated" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="193.155,185.5675,196.076,178.9951,193.155,181.9162,190.2339,178.9951,193.155,185.5675" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="83.9804" x="193.8853" y="152.3259">02 E04 A+B+C allocated</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="67.9146" x="201.9182" y="162.2721">current free = 3936</text><!--MD5=[f6fa3e1917b73de38ea03346a6903b17]
link Allocated to Fragmented--><path d="M184.4941,223.7385 C176.4611,240.3228 164.4191,265.181 155.3346,283.9342 " fill="none" id="Allocated-&gt;Fragmented" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="153.8083,287.0889,159.2954,282.4391,155.3952,283.8004,154.0338,279.9002,153.8083,287.0889" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="35.783" x="174.6866" y="253.8327">E05 free A</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="35.783" x="174.6866" y="263.7789">E06 free C</text><!--MD5=[c73bca393b062d6a86dff80fa900c78c]
link Fragmented to Coalesced--><path d="M92.7509,329.6414 C81.6363,335.9582 71.0474,344.1883 63.8982,354.7333 C56.391,365.8114 54.1053,380.4606 53.8278,393.0065 " fill="none" id="Fragmented-&gt;Coalesced" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="53.8132,396.4241,56.753,389.8601,53.8236,392.7728,50.9109,389.8434,53.8132,396.4241" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="47.4672" x="87.2666" y="363.2701">04 E07 free B</text><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="92.7436" x="64.6284" y="373.2163">merge previous, then next</text><!--MD5=[2b306524d92469efb3bb270d490680cf]
link Coalesced to OOMChecked--><path d="M55.8652,442.5257 C55.8652,457.3647 55.8652,476.9796 55.8652,491.9939 " fill="none" id="Coalesced-&gt;OOMChecked" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="55.8652,495.5941,58.7863,489.0217,55.8652,491.9427,52.9442,489.0217,55.8652,495.5941" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="82.5199" x="56.5955" y="472.7076">05 E08 request &gt; arena</text><!--MD5=[6b8be85e17f6174335a5329fe1414850]
link OOMChecked to *end--><path d="M55.8652,533.6993 C55.8652,546.2379 55.8652,562.6835 55.8652,573.4622 " fill="none" id="OOMChecked-&gt;*end" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="55.8652,576.8725,58.7863,570.3001,55.8652,573.2212,52.9442,570.3001,55.8652,576.8725" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><!--MD5=[b09143a670c8c67aa163b99fca5c6b6b]
link Allocated to MIN--><path d="M206.402,223.6581 C210.5791,230.1502 214.7489,237.7595 217.2537,245.2959 C235.6199,300.555 231.8517,317.8477 227.4774,375.911 C226.9589,382.7609 225.995,390.1731 224.958,396.8988 " fill="none" id="Allocated-&gt;MIN" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="224.403,400.3384,228.3223,394.3078,224.9778,396.7326,222.5531,393.3881,224.403,400.3384" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="81.0594" x="231.8006" y="313.6632">records low watermark</text><!--MD5=[1fa23b8554d20d5dd3f2f8930c0e2df3]
link Fragmented to MIN--><path d="M152.2237,332.9422 C158.409,345.9702 167.1649,362.5618 177.0892,375.911 C182.9094,383.7394 190.1317,391.4875 197.0254,398.2279 " fill="none" id="Fragmented-&gt;MIN" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="199.5813,400.6889,196.8641,394.0296,196.9477,398.1598,192.8176,398.2434,199.5813,400.6889" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="46.0067" x="177.8194" y="368.382">does not rise</text><!--MD5=[87522a40b34d64237ec6603d41372cd8]
link Coalesced to MIN--><path d="M107.6337,420.0409 C132.2582,420.0409 161.1402,420.0409 183.5812,420.0409 " fill="none" id="Coalesced-&gt;MIN" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><polygon fill="#8095A1" points="187.1595,420.0409,180.5871,417.1198,183.5082,420.0409,180.5871,422.962,187.1595,420.0409" style="stroke: #8095A1; stroke-width: 0.7302646103274287;"/><text fill="#000000" font-family="Monospace" font-size="7.3026" lengthAdjust="spacingAndGlyphs" textLength="54.7698" x="120.4937" y="415.4329">history remains</text><!--MD5=[ca62bd85e5915d2f6639cfa0fa77f8b6]
@startuml
scale 600 height
top to bottom direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 10
skinparam stateBorderColor #2c7794
skinparam stateBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A6 STATE — reusable states of the same RV32 arena
[*] - -> Free : 01 E01 one list node
Free - -> Allocated : 02 E04 A+B+C allocated\ncurrent free = 3936
Allocated - -> Fragmented : E05 free A\nE06 free C
Fragmented : 03 E06 two free blocks
Fragmented : sum free > largest block
Fragmented - -> Coalesced : 04 E07 free B\nmerge previous, then next
Coalesced : one free block
Coalesced : current = largest = initial
Coalesced - -> OOMChecked : 05 E08 request > arena
OOMChecked : NULL · hook=1 · PASS=1
OOMChecked - -> [*]
state "minimum-ever" as MIN
Allocated -right-> MIN : records low watermark
Fragmented -right-> MIN : does not rise
Coalesced -right-> MIN : history remains
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 12 KiB

+23
View File
@@ -0,0 +1,23 @@
@startuml
scale 820 width
left to right direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A7 RUNTIME — source identity, replay, memory and verdict
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
rectangle "<<checkpoint E06>>\n03 fragmented\nblocks=2 · free>largest" as E1
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
rectangle "<<checkpoint E08>>\n05 verified\nfinal=initial · blocks=1\nOOM=1 · PASS=1" as E2
SRC --> ELF : compile + link
ELF --> E1 : reset / load / replay
E1 --> MEM : inspect bytes
MEM --> E2 : continue
@enduml
+44
View File
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="82px" preserveAspectRatio="none" style="width:814px;height:82px;" version="1.1" viewBox="0 0 814 82" width="814.26px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="204.18" x="307.91" y="7.8893">A7 RUNTIME — source identity, replay, memory and verdict</text><!--MD5=[183d75e42a7a852d02a7f9ce2cc3343f]
entity SRC--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="77.9" x="4.92" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="31.16" x="13.12" y="37.7029">«source»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="38.54" x="13.12" y="47.7545">01 task03 C</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="61.5" x="13.12" y="57.8062">A/B/C experiment</text><!--MD5=[4a7b087cd571ae358eb895b9dc7ce0ed]
entity ELF--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="71.34" x="179.58" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="31.98" x="187.78" y="37.7029">«artifact»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="50.84" x="187.78" y="47.7545">02 ELF + image</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="54.94" x="187.78" y="57.8062">heap_4 symbols</text><!--MD5=[45565a74ca8123df0b8413ce5340d40a]
entity E1--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="92.66" x="367.36" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="59.86" x="375.56" y="37.7029">«checkpoint E06»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="51.66" x="375.56" y="47.7545">03 fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="76.26" x="375.56" y="57.8062">blocks=2 · free&gt;largest</text><!--MD5=[5ceda9279414f57783e95166b8d927b7]
entity MEM--><rect fill="#EDF6FA" height="46.5549" style="stroke: #2C7794; stroke-width: 1.23;" width="80.36" x="555.96" y="21.6136"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="36.9" x="564.16" y="37.7029">«memory»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="58.22" x="564.16" y="47.7545">04 ucHeap[4096]</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="63.96" x="564.16" y="57.8062">headers + payload</text><!--MD5=[a3c437a7ee715155cf6a0fec80d7cbaf]
entity E2--><rect fill="#EDF6FA" height="56.6065" style="stroke: #2C7794; stroke-width: 1.23;" width="87.74" x="717.5" y="16.587"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="59.86" x="725.7" y="32.6763">«checkpoint E08»</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="36.08" x="725.7" y="42.7279">05 verified</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="71.34" x="725.7" y="52.7796">final=initial · blocks=1</text><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="56.58" x="725.7" y="62.8312">OOM=1 · PASS=1</text><!--MD5=[2e73c4d4efa4a7715d66b06010e70f85]
link SRC to ELF--><path d="M83.2054,44.8852 C110.372,44.8852 146.6734,44.8852 174.209,44.8852 " fill="none" id="SRC-&gt;ELF" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="178.0056,44.8852,170.6256,41.6052,173.9056,44.8852,170.6256,48.1652,178.0056,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="45.92" x="108.24" y="42.1145">compile + link</text><!--MD5=[98439561a91d683361f6e8599ebb304f]
link ELF to E1--><path d="M251.2562,44.8852 C282.0636,44.8852 327.221,44.8852 361.9726,44.8852 " fill="none" id="ELF-&gt;E1" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="365.9988,44.8852,358.6188,41.6052,361.8988,44.8852,358.6188,48.1652,365.9988,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="65.6" x="276.34" y="42.1145">reset / load / replay</text><!--MD5=[14b84038a04448f34eb55bd119f2d935]
link E1 to MEM--><path d="M460.3726,44.8852 C488.0476,44.8852 523.1518,44.8852 550.6136,44.8852 " fill="none" id="E1-&gt;MEM" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="554.4102,44.8852,547.0302,41.6052,550.3102,44.8852,547.0302,48.1652,554.4102,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="45.1" x="485.44" y="42.1145">inspect bytes</text><!--MD5=[28f0a5a321106494a7afb95cbc1e35b0]
link MEM to E2--><path d="M636.5578,44.8852 C659.3374,44.8852 688.1276,44.8852 712.2274,44.8852 " fill="none" id="MEM-&gt;E2" style="stroke: #8095A1; stroke-width: 0.82;"/><polygon fill="#8095A1" points="716.0568,44.8852,708.6768,41.6052,711.9568,44.8852,708.6768,48.1652,716.0568,44.8852" style="stroke: #8095A1; stroke-width: 0.82;"/><text fill="#000000" font-family="Monospace" font-size="7.38" lengthAdjust="spacingAndGlyphs" textLength="30.34" x="661.74" y="42.1145">continue</text><!--MD5=[d3cc7590ea240485cc9ae283b10caa4d]
@startuml
scale 820 width
left to right direction
skinparam backgroundColor transparent
skinparam shadowing false
skinparam defaultFontName Monospace
skinparam defaultFontSize 9
skinparam rectangleBorderColor #2c7794
skinparam rectangleBackgroundColor #edf6fa
skinparam ArrowColor #8095a1
title A7 RUNTIME — source identity, replay, memory and verdict
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
rectangle "<<checkpoint E06>>\n03 fragmented\nblocks=2 · free>largest" as E1
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
rectangle "<<checkpoint E08>>\n05 verified\nfinal=initial · blocks=1\nOOM=1 · PASS=1" as E2
SRC - -> ELF : compile + link
ELF - -> E1 : reset / load / replay
E1 - -> MEM : inspect bytes
MEM - -> E2 : continue
@enduml
PlantUML version 1.2020.02(Sun Mar 01 11:22:07 CET 2020)
(GPL source distribution)
Java Runtime: OpenJDK Runtime Environment
JVM: OpenJDK 64-Bit Server VM
Java Version: 25.0.4-ea+4-1-Debian
Operating System: Linux
Default Encoding: UTF-8
Language: en
Country: null
--></g></svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

+15
View File
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="pl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="card-renderer" content="react">
<title>Karta pracy</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="app.css">
</head>
<body class="resource-header-enabled">
<div id="root"></div>
<script type="module" src="app.js"></script>
</body>
</html>
+43
View File
File diff suppressed because one or more lines are too long