Compare commits
12 Commits
c05df87c02
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4785d506fc | |||
| 48eccb5e24 | |||
| bd34c7ec1e | |||
| 2b17bb4ff9 | |||
| 032a06fdef | |||
| 8aee0b104c | |||
| 49cabf2077 | |||
| ef1854cfa0 | |||
| a40d2916df | |||
| d589bb8c41 | |||
| f4973842ad | |||
| 62fb0f8849 |
@@ -1,18 +1,18 @@
|
|||||||
*.aux
|
.stem/
|
||||||
*.log
|
|
||||||
*.out
|
|
||||||
*.fls
|
|
||||||
*.fdb_latexmk
|
|
||||||
*.synctex.gz
|
|
||||||
*.pdf
|
|
||||||
build-meta.tex
|
|
||||||
.rv/
|
|
||||||
.nvim/
|
|
||||||
.vim/
|
|
||||||
.build/
|
|
||||||
.gdb_history
|
|
||||||
host-build/
|
host-build/
|
||||||
build/*/prog.bin
|
build/*/prog.bin
|
||||||
build/*/prog.elf
|
build/*/prog.elf
|
||||||
build/*/prog.lst
|
build/*/prog.lst
|
||||||
build/*/prog.map
|
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
|
||||||
|
|||||||
@@ -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})
|
||||||
@@ -6,11 +6,18 @@ OBJDUMP := $(RISCV_PREFIX)objdump
|
|||||||
SIZE := $(RISCV_PREFIX)size
|
SIZE := $(RISCV_PREFIX)size
|
||||||
HOST_CC ?= cc
|
HOST_CC ?= cc
|
||||||
|
|
||||||
DEBUG ?= 1
|
PROFILE ?= observe
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(PROFILE),observe)
|
||||||
|
OPTFLAGS := -O0 -fno-omit-frame-pointer -fno-inline -fno-optimize-sibling-calls
|
||||||
DBGFLAGS := -g3 -ggdb
|
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 :=
|
DBGFLAGS :=
|
||||||
|
else
|
||||||
|
$(error PROFILE must be observe, debug or release)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
RV_ENV_ROOT ?= /opt/rv-env
|
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
|
LAB_RUNTIME_DIR ?= $(RV_ENV_ROOT)/vendor/lab-runtime
|
||||||
MEMOPS ?= $(LAB_RUNTIME_DIR)/memops.c
|
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
|
BUILD_ROOT ?= build
|
||||||
HOST_BUILD_ROOT ?= host-build
|
HOST_BUILD_ROOT ?= host-build
|
||||||
TASKS := \
|
TASKS := \
|
||||||
task01_heap_map \
|
task01_first_fit_split \
|
||||||
task02_free_list \
|
task02_address_order_coalesce \
|
||||||
task03_heap_init \
|
task03_freertos_heap4
|
||||||
task04_alignment \
|
|
||||||
task05_malloc_first_fit \
|
|
||||||
task06_split_block \
|
|
||||||
task07_free_insert \
|
|
||||||
task08_coalescing \
|
|
||||||
task09_config_macros \
|
|
||||||
task10_heap4_demo
|
|
||||||
|
|
||||||
ARCH ?= rv32i_zicsr_zifencei
|
ARCH ?= rv32i_zicsr_zifencei
|
||||||
ABI ?= ilp32
|
ABI ?= ilp32
|
||||||
|
COMMON_FLAGS := -std=c11 -march=$(ARCH) -mabi=$(ABI) -nostdlib -nostartfiles \
|
||||||
COMMON_FLAGS := -std=c99 -march=$(ARCH) -mabi=$(ABI) -nostdlib -nostartfiles -ffreestanding -fno-builtin -fno-stack-protector $(DBGFLAGS) -Wall -Wextra -Isrc/tasks
|
-ffreestanding -fno-builtin -fno-stack-protector -ffunction-sections \
|
||||||
LINK_FLAGS := -Wl,--no-relax -Wl,-T,$(LDSCRIPT)
|
-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
|
LIBS := -lgcc
|
||||||
EMIT_FLAGS := -std=c99 -march=$(ARCH) -mabi=$(ABI) -O -ffreestanding -fno-builtin -fno-stack-protector -nostdlib -nostartfiles -Wall -Wextra -Isrc/tasks
|
HOST_FLAGS := -std=c11 $(OPTFLAGS) $(DBGFLAGS) -Wall -Wextra -Wpedantic \
|
||||||
CFLAGS_STEP := $(COMMON_FLAGS) -O
|
-DHOST_PRINTF=1 -Isrc/tasks
|
||||||
HOST_CFLAGS := -std=c99 -O0 -g -Wall -Wextra -DHOST_PRINTF=1 -Isrc/tasks
|
HOST_HEAP4_FLAGS := $(HOST_FLAGS) -DHEAP4_HOST_ADAPTER=1 -Iinclude/host-shim
|
||||||
|
|
||||||
.PHONY: all tasks host \
|
.PHONY: all tasks host task1 task2 task3 t1 t2 t3 \
|
||||||
task1 task2 task3 task4 task5 task6 task7 task8 task9 task10 \
|
host-task1 host-task2 host-task3 ht1 ht2 ht3 clean check-support check-kernel \
|
||||||
t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 \
|
$(TASKS)
|
||||||
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)
|
|
||||||
|
|
||||||
all: tasks
|
all: tasks
|
||||||
tasks: $(TASKS)
|
tasks: $(TASKS)
|
||||||
@@ -59,54 +65,66 @@ host: $(addprefix $(HOST_BUILD_ROOT)/,$(addsuffix /prog,$(TASKS)))
|
|||||||
task1 t1: $(word 1,$(TASKS))
|
task1 t1: $(word 1,$(TASKS))
|
||||||
task2 t2: $(word 2,$(TASKS))
|
task2 t2: $(word 2,$(TASKS))
|
||||||
task3 t3: $(word 3,$(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-task1 ht1: $(HOST_BUILD_ROOT)/$(word 1,$(TASKS))/prog
|
||||||
host-task2 ht2: $(HOST_BUILD_ROOT)/$(word 2,$(TASKS))/prog
|
host-task2 ht2: $(HOST_BUILD_ROOT)/$(word 2,$(TASKS))/prog
|
||||||
host-task3 ht3: $(HOST_BUILD_ROOT)/$(word 3,$(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:
|
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 "$(LDSCRIPT)" || { echo "Missing $(LDSCRIPT)." >&2; exit 1; }
|
||||||
@test -f "$(MEMOPS)" || { echo "Missing $(MEMOPS)." >&2; exit 1; }
|
@test -f "$(MEMOPS)" || { echo "Missing $(MEMOPS)." >&2; exit 1; }
|
||||||
|
|
||||||
define task_rules
|
check-kernel:
|
||||||
$(1): $(BUILD_ROOT)/$(1)/prog.bin $(BUILD_ROOT)/$(1)/prog.elf $(BUILD_ROOT)/$(1)/prog.lst $(BUILD_ROOT)/$(1)/$(1).s
|
@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)
|
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 $$@
|
$(SIZE) -A -x $$@
|
||||||
|
|
||||||
$(BUILD_ROOT)/$(1)/prog.bin: $(BUILD_ROOT)/$(1)/prog.elf
|
$(BUILD_ROOT)/$(1)/prog.bin: $(BUILD_ROOT)/$(1)/prog.elf
|
||||||
$(OBJCOPY) -O binary $$< $$@
|
$(OBJCOPY) -O binary $$< $$@
|
||||||
|
|
||||||
$(BUILD_ROOT)/$(1)/prog.lst: $(BUILD_ROOT)/$(1)/prog.elf
|
$(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)
|
mkdir -p $$(@D)
|
||||||
$(CC) $(EMIT_FLAGS) -S -o $$@ $$<
|
$(HOST_CC) $(HOST_FLAGS) -o $$@ $$<
|
||||||
|
|
||||||
$(HOST_BUILD_ROOT)/$(1)/prog: src/tasks/$(1).c src/tasks/heap4_common.h
|
|
||||||
mkdir -p $$(@D)
|
|
||||||
$(HOST_CC) $(HOST_CFLAGS) -o $$@ $$<
|
|
||||||
endef
|
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:
|
clean:
|
||||||
rm -rf $(BUILD_ROOT) $(HOST_BUILD_ROOT)
|
rm -rf $(BUILD_ROOT) $(HOST_BUILD_ROOT)
|
||||||
|
|||||||
@@ -1,45 +1,106 @@
|
|||||||
# 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
|
1. nagłówek, wyrównanie i geometria splitu na arenie 256 B;
|
||||||
uruchamianych w środowisku RV32I.
|
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
|
W lekcji 30-minutowej programy 1–2 są demonstracjami z predykcją. Uczeń
|
||||||
jednokierunkowej, `static`, `typedef`, makr i arytmetyki adresów, ale nie
|
debugguje wyłącznie program 3.
|
||||||
wymaga jeszcze schedulera, tasków ani przerwań.
|
|
||||||
|
|
||||||
Kod w `src/tasks` jest dydaktycznym modelem zachowania `heap_4`, a nie kopią
|
Task 3 linkuje upstream `portable/MemMang/heap_4.c` z commita
|
||||||
pliku upstream FreeRTOS.
|
`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.
|
## Bezpośrednia kontynuacja K&R 5.4
|
||||||
- `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.
|
|
||||||
|
|
||||||
Hostowe `printf` jest dostępne tylko przez `-DHOST_PRINTF=1`; RV32I zapisuje
|
Lekcja zaczyna się od gotowego projektu z poprzedniej karty:
|
||||||
wyniki w globalnych zmiennych `volatile`.
|
`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
|
```bash
|
||||||
RV_ENV_ROOT=~/dev/workspace/rv/tools/rv32i-hazard3-student-env make tasks
|
stemctl debug rp2350 freertos heap4 3 --device /dev/bus/usb/BBB/DDD
|
||||||
make host
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Praca przez rvctl
|
Pełna weryfikacja repozytorium wykonywana poza 30-minutową lekcją:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./rvctl series cards fetch inf heap4
|
stemctl series cards fetch freertos heap4
|
||||||
./rvctl card use inf heap4
|
stemctl test native-amd64 freertos heap4 1
|
||||||
./rvctl tasks list
|
stemctl test hazard3-sim freertos heap4 2
|
||||||
./rvctl debug rv32i 1
|
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_fragmented_checkpoint`.
|
||||||
|
|
||||||
|
```gdb
|
||||||
|
p g_fragmented_stats
|
||||||
|
p g_final_stats
|
||||||
|
p xFreeBytesRemaining
|
||||||
|
p xMinimumEverFreeBytesRemaining
|
||||||
|
p xStart
|
||||||
|
p pxEnd
|
||||||
|
x/160bx ucHeap
|
||||||
|
b prvInsertBlockIntoFreeList
|
||||||
|
b pvPortMalloc
|
||||||
|
b vPortFree
|
||||||
|
```
|
||||||
|
|
||||||
|
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).
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
|
After Width: | Height: | Size: 28 KiB |
@@ -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
|
||||||
@@ -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->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->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->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->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 |
|
After Width: | Height: | Size: 28 KiB |
@@ -0,0 +1,48 @@
|
|||||||
|
@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 — in-band metadata and address order
|
||||||
|
|
||||||
|
class "01 Block header" as HEADER {
|
||||||
|
next : BlockLink_t*
|
||||||
|
size : size_t
|
||||||
|
}
|
||||||
|
class "Allocated block" as ALLOC {
|
||||||
|
02 header + 13 byte request
|
||||||
|
aligned total = 32 bytes
|
||||||
|
payload begins after header
|
||||||
|
}
|
||||||
|
class "03 Free remainder" as REM {
|
||||||
|
own header
|
||||||
|
size = 224 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADER *-- ALLOC : precedes payload
|
||||||
|
ALLOC -down-> REM : split preserves 256
|
||||||
|
|
||||||
|
class "04 Address-ordered free list" as LIST {
|
||||||
|
previous < inserted < current
|
||||||
|
}
|
||||||
|
class "05 Right neighbour" as RIGHT {
|
||||||
|
block + block.size == current
|
||||||
|
}
|
||||||
|
class "06 Left neighbour" as LEFT {
|
||||||
|
previous + previous.size == block
|
||||||
|
}
|
||||||
|
|
||||||
|
REM -down-> LIST : insert by address
|
||||||
|
LIST -down-> RIGHT : join first
|
||||||
|
RIGHT -down-> LEFT : then join left
|
||||||
|
|
||||||
|
note right of LIST
|
||||||
|
Ordering makes both physical
|
||||||
|
neighbours locally visible.
|
||||||
|
end note
|
||||||
|
@enduml
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?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.2921px" preserveAspectRatio="none" style="width:295px;height:620px;" version="1.1" viewBox="0 0 295 620" width="295.9262px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="202.1522" x="49.1929" y="8.2167">A2 STRUCTURE — in-band metadata and address order</text><!--MD5=[9827fb78ff6e3f59cfadf959dc26af7c]
|
||||||
|
class HEADER--><rect fill="#EDF6FA" height="54.7579" id="HEADER" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="81.4758" x="29.5926" y="16.4642"/><ellipse cx="39.5849" cy="27.2252" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M40.5698,29.7593 Q40.3055,29.8914 40.0173,29.9515 Q39.7291,30.0235 39.4048,30.0235 Q38.2758,30.0235 37.6753,29.2789 Q37.0869,28.5343 37.0869,27.1171 Q37.0869,25.6999 37.6753,24.9553 Q38.2758,24.2107 39.4048,24.2107 Q39.7291,24.2107 40.0173,24.2828 Q40.3175,24.3428 40.5698,24.4749 L40.5698,25.7119 Q40.2815,25.4477 40.0053,25.3276 Q39.7411,25.2075 39.4648,25.2075 Q38.8523,25.2075 38.5401,25.6879 Q38.2278,26.1683 38.2278,27.1171 Q38.2278,28.0659 38.5401,28.5463 Q38.8523,29.0267 39.4648,29.0267 Q39.7411,29.0267 40.0053,28.9066 Q40.2815,28.7865 40.5698,28.5223 L40.5698,29.7593 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="59.9539" x="48.8086" y="30.2075">01 Block header</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="30.3613" x2="110.2998" y1="37.9862" y2="37.9862"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="68.4089" x="34.2045" y="49.2775">next : BlockLink_t*</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="42.2752" x="34.2045" y="59.7463">size : size_t</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="30.3613" x2="110.2998" y1="65.073" y2="65.073"/><!--MD5=[40d637119be40bcfdc4ce848efbdda9e]
|
||||||
|
class ALLOC--><rect fill="#EDF6FA" height="65.2267" id="ALLOC" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="114.5273" x="13.0669" y="128.8701"/><ellipse cx="39.6618" cy="139.631" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M40.6466,142.1652 Q40.3824,142.2973 40.0942,142.3573 Q39.8059,142.4294 39.4816,142.4294 Q38.3527,142.4294 37.7522,141.6848 Q37.1637,140.9401 37.1637,139.523 Q37.1637,138.1058 37.7522,137.3612 Q38.3527,136.6165 39.4816,136.6165 Q39.8059,136.6165 40.0942,136.6886 Q40.3944,136.7486 40.6466,136.8808 L40.6466,138.1178 Q40.3584,137.8536 40.0821,137.7335 Q39.8179,137.6134 39.5417,137.6134 Q38.9292,137.6134 38.6169,138.0938 Q38.3047,138.5742 38.3047,139.523 Q38.3047,140.4717 38.6169,140.9521 Q38.9292,141.4325 39.5417,141.4325 Q39.8179,141.4325 40.0821,141.3124 Q40.3584,141.1923 40.6466,140.9281 L40.6466,142.1652 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="56.1107" x="52.5749" y="142.6134">Allocated block</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="150.392" y2="150.392"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="105.3036" x="17.6787" y="161.6833">02 header + 13 byte request</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="88.3935" x="17.6787" y="172.1522">aligned total = 32 bytes</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="104.535" x="17.6787" y="182.621">payload begins after header</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="187.9477" y2="187.9477"/><!--MD5=[71c2adef9be32489055f250a531e7c6f]
|
||||||
|
class REM--><rect fill="#EDF6FA" height="54.7579" id="REM" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="89.9308" x="25.3651" y="251.7448"/><ellipse cx="35.3574" cy="262.5058" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M36.3422,265.0399 Q36.078,265.172 35.7898,265.232 Q35.5015,265.3041 35.1773,265.3041 Q34.0483,265.3041 33.4478,264.5595 Q32.8593,263.8148 32.8593,262.3977 Q32.8593,260.9805 33.4478,260.2359 Q34.0483,259.4913 35.1773,259.4913 Q35.5015,259.4913 35.7898,259.5633 Q36.09,259.6234 36.3422,259.7555 L36.3422,260.9925 Q36.054,260.7283 35.7778,260.6082 Q35.5135,260.4881 35.2373,260.4881 Q34.6248,260.4881 34.3125,260.9685 Q34.0003,261.4489 34.0003,262.3977 Q34.0003,263.3465 34.3125,263.8269 Q34.6248,264.3073 35.2373,264.3073 Q35.5135,264.3073 35.7778,264.1872 Q36.054,264.0671 36.3422,263.8028 L36.3422,265.0399 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="68.4089" x="44.5811" y="265.4881">03 Free remainder</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="26.1337" x2="114.5273" y1="273.2667" y2="273.2667"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="43.8125" x="29.9769" y="284.558">own header</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="59.9539" x="29.9769" y="295.0269">size = 224 bytes</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="26.1337" x2="114.5273" y1="300.3535" y2="300.3535"/><!--MD5=[b0a0edd67d9eafaaa5639bbe6382adce]
|
||||||
|
class LIST--><rect fill="#EDF6FA" height="44.289" id="LIST" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="124.5196" x="8.0707" y="364.1506"/><ellipse cx="18.063" cy="374.9116" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M19.0478,377.4457 Q18.7836,377.5778 18.4954,377.6379 Q18.2071,377.7099 17.8829,377.7099 Q16.7539,377.7099 16.1534,376.9653 Q15.565,376.2207 15.565,374.8035 Q15.565,373.3863 16.1534,372.6417 Q16.7539,371.8971 17.8829,371.8971 Q18.2071,371.8971 18.4954,371.9692 Q18.7956,372.0292 19.0478,372.1613 L19.0478,373.3983 Q18.7596,373.1341 18.4834,373.014 Q18.2192,372.8939 17.9429,372.8939 Q17.3304,372.8939 17.0182,373.3743 Q16.7059,373.8547 16.7059,374.8035 Q16.7059,375.7523 17.0182,376.2327 Q17.3304,376.7131 17.9429,376.7131 Q18.2192,376.7131 18.4834,376.593 Q18.7596,376.4729 19.0478,376.2087 L19.0478,377.4457 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="102.9977" x="27.2867" y="377.8939">04 Address-ordered free list</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="8.8394" x2="131.8217" y1="385.6726" y2="385.6726"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="107.6095" x="12.6826" y="396.9639">previous < inserted < current</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="8.8394" x2="131.8217" y1="402.2905" y2="402.2905"/><!--MD5=[490fcd32b6546c9bc615869efabd094a]
|
||||||
|
class RIGHT--><rect fill="#EDF6FA" height="44.289" id="RIGHT" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="114.5273" x="13.0669" y="466.0876"/><ellipse cx="33.0899" cy="476.8486" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M34.0748,479.3827 Q33.8105,479.5148 33.5223,479.5748 Q33.2341,479.6469 32.9098,479.6469 Q31.7808,479.6469 31.1803,478.9023 Q30.5919,478.1577 30.5919,476.7405 Q30.5919,475.3233 31.1803,474.5787 Q31.7808,473.8341 32.9098,473.8341 Q33.2341,473.8341 33.5223,473.9061 Q33.8225,473.9662 34.0748,474.0983 L34.0748,475.3353 Q33.7865,475.0711 33.5103,474.951 Q33.2461,474.8309 32.9698,474.8309 Q32.3573,474.8309 32.0451,475.3113 Q31.7328,475.7917 31.7328,476.7405 Q31.7328,477.6893 32.0451,478.1697 Q32.3573,478.6501 32.9698,478.6501 Q33.2461,478.6501 33.5103,478.53 Q33.7865,478.4099 34.0748,478.1457 L34.0748,479.3827 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="70.7148" x="44.5427" y="479.8309">05 Right neighbour</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="487.6095" y2="487.6095"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="105.3036" x="17.6787" y="498.9008">block + block.size == current</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="504.2275" y2="504.2275"/><!--MD5=[007d3a1820cefd008c8dbdad7e6fdec6]
|
||||||
|
class LEFT--><rect fill="#EDF6FA" height="44.289" id="LEFT" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="131.4374" x="4.6118" y="568.0246"/><ellipse cx="34.7809" cy="578.7855" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M35.7658,581.3197 Q35.5015,581.4518 35.2133,581.5118 Q34.9251,581.5839 34.6008,581.5839 Q33.4718,581.5839 32.8713,580.8393 Q32.2829,580.0946 32.2829,578.6775 Q32.2829,577.2603 32.8713,576.5157 Q33.4718,575.771 34.6008,575.771 Q34.9251,575.771 35.2133,575.8431 Q35.5135,575.9032 35.7658,576.0353 L35.7658,577.2723 Q35.4775,577.0081 35.2013,576.888 Q34.9371,576.7679 34.6608,576.7679 Q34.0483,576.7679 33.7361,577.2483 Q33.4238,577.7287 33.4238,578.6775 Q33.4238,579.6262 33.7361,580.1066 Q34.0483,580.587 34.6608,580.587 Q34.9371,580.587 35.2013,580.4669 Q35.4775,580.3468 35.7658,580.0826 L35.7658,581.3197 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="65.3344" x="48.2321" y="581.7679">06 Left neighbour</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="5.3805" x2="135.2806" y1="589.5465" y2="589.5465"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="122.2137" x="9.2237" y="600.8378">previous + previous.size == block</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="5.3805" x2="135.2806" y1="606.1645" y2="606.1645"/><path d="M159.877,371.9831 L159.877,383.2206 L132.7671,386.2952 L159.877,389.3697 L159.877,400.6072 A0,0 0 0 0 159.877,400.6072 L286.7025,400.6072 A0,0 0 0 0 286.7025,400.6072 L286.7025,379.6695 L279.0161,371.9831 L159.877,371.9831 A0,0 0 0 0 159.877,371.9831 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7686395199937726;"/><path d="M279.0161,371.9831 L279.0161,379.6695 L286.7025,379.6695 L279.0161,371.9831 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="110.6841" x="164.4889" y="384.043">Ordering makes both physical</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="96.0799" x="164.4889" y="394.5119">neighbours locally visible.</text><!--MD5=[fc2657b7de304bb41a5d36ac60748945]
|
||||||
|
reverse link HEADER to ALLOC--><path d="M70.3305,82.6749 C70.3305,97.5173 70.3305,114.3505 70.3305,128.5626 " fill="none" id="HEADER<-ALLOC" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,72.7056,67.256,77.3174,70.3305,81.9293,73.4051,77.3174,70.3305,72.7056" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="65.3344" x="71.0992" y="103.2667">precedes payload</text><!--MD5=[bb73b5a7e21afff1a1d0c43dcbd5d11a]
|
||||||
|
link ALLOC to REM--><path d="M70.3305,194.2813 C70.3305,210.5842 70.3305,230.3382 70.3305,246.6026 " fill="none" id="ALLOC->REM" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,250.3689,73.4051,243.4512,70.3305,246.5257,67.256,243.4512,70.3305,250.3689" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="70.7148" x="71.0992" y="226.1414">split preserves 256</text><!--MD5=[32aec76f28e14f88b0d74d9f592c80fb]
|
||||||
|
link REM to LIST--><path d="M70.3305,306.8178 C70.3305,322.8901 70.3305,343.1975 70.3305,359.1622 " fill="none" id="REM->LIST" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,362.8055,73.4051,355.8878,70.3305,358.9623,67.256,355.8878,70.3305,362.8055" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="63.7971" x="71.0992" y="338.5473">insert by address</text><!--MD5=[6bd3103bbaa36e7d502940b82c286473]
|
||||||
|
link LIST to RIGHT--><path d="M70.3305,408.6011 C70.3305,423.9508 70.3305,444.681 70.3305,461.0377 " fill="none" id="LIST->RIGHT" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,464.7963,73.4051,457.8786,70.3305,460.9531,67.256,457.8786,70.3305,464.7963" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="30.7456" x="71.0992" y="440.4842">join first</text><!--MD5=[f41c07ebada6943a8deaf240fd528885]
|
||||||
|
link RIGHT to LEFT--><path d="M70.3305,510.538 C70.3305,525.8878 70.3305,546.618 70.3305,562.9746 " fill="none" id="RIGHT->LEFT" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,566.7333,73.4051,559.8155,70.3305,562.8901,67.256,559.8155,70.3305,566.7333" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="47.6557" x="71.0992" y="542.4212">then join left</text><!--MD5=[83344144544ae5f259c61315a4ceaf0d]
|
||||||
|
@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 — in-band metadata and address order
|
||||||
|
|
||||||
|
class "01 Block header" as HEADER {
|
||||||
|
next : BlockLink_t*
|
||||||
|
size : size_t
|
||||||
|
}
|
||||||
|
class "Allocated block" as ALLOC {
|
||||||
|
02 header + 13 byte request
|
||||||
|
aligned total = 32 bytes
|
||||||
|
payload begins after header
|
||||||
|
}
|
||||||
|
class "03 Free remainder" as REM {
|
||||||
|
own header
|
||||||
|
size = 224 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADER *- - ALLOC : precedes payload
|
||||||
|
ALLOC -down-> REM : split preserves 256
|
||||||
|
|
||||||
|
class "04 Address-ordered free list" as LIST {
|
||||||
|
previous < inserted < current
|
||||||
|
}
|
||||||
|
class "05 Right neighbour" as RIGHT {
|
||||||
|
block + block.size == current
|
||||||
|
}
|
||||||
|
class "06 Left neighbour" as LEFT {
|
||||||
|
previous + previous.size == block
|
||||||
|
}
|
||||||
|
|
||||||
|
REM -down-> LIST : insert by address
|
||||||
|
LIST -down-> RIGHT : join first
|
||||||
|
RIGHT -down-> LEFT : then join left
|
||||||
|
|
||||||
|
note right of LIST
|
||||||
|
Ordering makes both physical
|
||||||
|
neighbours locally visible.
|
||||||
|
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: 15 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -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 — allocate, fragment, coalesce, verify
|
||||||
|
|
||||||
|
rectangle "01 RESET\ninitial free = 4080" as S1
|
||||||
|
rectangle "02 ALLOC A\n24 byte payload\nfirst-fit + split" as S2
|
||||||
|
rectangle "03 ALLOC B / C\n40 + 16 byte payload\nafter = 3952" as S3
|
||||||
|
rectangle "04 FREE A / C\nB remains allocated" as S4
|
||||||
|
rectangle "05 E01 FRAGMENTED\n2 free blocks\ncurrent > largest" as S5
|
||||||
|
rectangle "06 FREE B\ninsert by address\njoin right + left" as S6
|
||||||
|
rectangle "07 E02 COALESCED\n1 free block\nfinal = initial" as S7
|
||||||
|
rectangle "08 OOM CHECK\nNULL · hook=1\nasserts=0 · PASS=1" as S8
|
||||||
|
|
||||||
|
S1 -right-> S2 : pvPortMalloc
|
||||||
|
S2 -right-> S3 : split remainder
|
||||||
|
S3 -right-> S4 : vPortFree
|
||||||
|
S4 -down-> S5 : heap stats
|
||||||
|
S5 -left-> S6 : continue
|
||||||
|
S6 -left-> S7 : coalesce
|
||||||
|
S7 -left-> S8 : oversized request
|
||||||
|
@enduml
|
||||||
@@ -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="263.7004px" preserveAspectRatio="none" style="width:811px;height:263px;" version="1.1" viewBox="0 0 811 263" width="811.5712px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="231.1894" x="294.4053" y="11.5848">A5 FLOW — allocate, fragment, coalesce, verify</text><!--MD5=[d0cae5ff9305becd6f502d4fe4f41481]
|
||||||
|
entity S1--><rect fill="#EDF6FA" height="53.6024" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="108.37" x="7.2247" y="32.316"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="45.7562" x="19.2658" y="55.942">01 RESET</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="84.2878" x="19.2658" y="70.7021">initial free = 4080</text><!--MD5=[d3395af3100fe8cebf35265100c4415f]
|
||||||
|
entity S2--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="104.7577" x="224.5668" y="24.9348"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="59.0015" x="236.6079" y="48.5608">02 ALLOC A</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="80.6755" x="236.6079" y="63.3209">24 byte payload</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="63.8179" x="236.6079" y="78.081">first-fit + split</text><!--MD5=[6c7192638421eaf134d201765ac5db29]
|
||||||
|
entity S3--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="127.6358" x="450.3377" y="24.9348"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="74.6549" x="462.3789" y="48.5608">03 ALLOC B / C</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="103.5536" x="462.3789" y="63.3209">40 + 16 byte payload</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="59.0015" x="462.3789" y="78.081">after = 3952</text><!--MD5=[01b905ebe31ca24275b86a9951c478d0]
|
||||||
|
entity S4--><rect fill="#EDF6FA" height="53.6024" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="121.6153" x="671.2922" y="32.316"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="65.022" x="683.3333" y="55.942">04 FREE A / C</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="97.533" x="683.3333" y="70.7021">B remains allocated</text><!--MD5=[099bd2cf1f4f3a6dbf2f1fde6174f38e]
|
||||||
|
entity S5--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="132.4523" x="665.8737" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="108.37" x="677.9148" y="206.0345">05 E01 FRAGMENTED</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="62.6138" x="677.9148" y="220.7946">2 free blocks</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="84.2878" x="677.9148" y="235.5547">current > largest</text><!--MD5=[0656c7721b015b9ca8cf2e2c2e8f5aee]
|
||||||
|
entity S6--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="111.9824" x="465.3891" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="49.3686" x="477.4302" y="206.0345">06 FREE B</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="87.9001" x="477.4302" y="220.7946">insert by address</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="72.2467" x="477.4302" y="235.5547">join right + left</text><!--MD5=[6ba532df225878998c5769132c3837e2]
|
||||||
|
entity S7--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="121.6153" x="258.2819" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="97.533" x="270.3231" y="206.0345">07 E02 COALESCED</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="57.7974" x="270.3231" y="220.7946">1 free block</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="59.0015" x="270.3231" y="235.5547">final = initial</text><!--MD5=[ce611cd767df6ac8a45071985dabb378]
|
||||||
|
entity S8--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="115.5947" x="8.4288" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="79.4714" x="20.4699" y="206.0345">08 OOM CHECK</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="73.4508" x="20.4699" y="220.7946">NULL · hook=1</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="91.5125" x="20.4699" y="235.5547">asserts=0 · PASS=1</text><!--MD5=[15cb110786dd224ca6a510a3d2a24e20]
|
||||||
|
link S1 to S2--><path d="M115.7994,59.1196 C146.5043,59.1196 184.9515,59.1196 216.5956,59.1196 " fill="none" id="S1->S2" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="222.2429,59.1196,211.4059,54.3031,216.2223,59.1196,211.4059,63.936,222.2429,59.1196" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="65.022" x="137.5698" y="51.4386">pvPortMalloc</text><!--MD5=[8eac89d31ced3c9003fbd6a8a005c745]
|
||||||
|
link S2 to S3--><path d="M329.5894,59.1196 C362.7266,59.1196 405.9181,59.1196 442.1979,59.1196 " fill="none" id="S2->S3" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="448.0018,59.1196,437.1648,54.3031,441.9812,59.1196,437.1648,63.936,448.0018,59.1196" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="77.0631" x="351.2996" y="51.4386">split remainder</text><!--MD5=[82e284a09e4ebade00512bdc77bff32c]
|
||||||
|
link S3 to S4--><path d="M578.3709,59.1196 C605.1142,59.1196 636.2044,59.1196 663.4053,59.1196 " fill="none" id="S3->S4" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="669.1369,59.1196,658.2999,54.3031,663.1163,59.1196,658.2999,63.936,669.1369,59.1196" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="49.3686" x="599.9486" y="51.4386">vPortFree</text><!--MD5=[0e6b031b378ab8978eaa734a548bdfb6]
|
||||||
|
link S4 to S5--><path d="M732.0999,86.2723 C732.0999,110.3906 732.0999,146.6826 732.0999,174.6541 " fill="none" id="S4->S5" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="732.0999,180.494,736.9163,169.657,732.0999,174.4735,727.2834,169.657,732.0999,180.494" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="51.7768" x="733.304" y="142.2166">heap stats</text><!--MD5=[3c9aaad44b43c509ca535c241fdd0151]
|
||||||
|
reverse link S6 to S5--><path d="M585.5595,216.5812 C610.8338,216.5812 639.8529,216.5812 665.368,216.5812 " fill="none" id="S6<-S5" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="579.6714,216.5812,590.5084,221.3977,585.6919,216.5812,590.5084,211.7648,579.6714,216.5812" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="44.5521" x="599.3465" y="208.9003">continue</text><!--MD5=[5f6ea4567bb0950bff1d27387d49b4c2]
|
||||||
|
reverse link S7 to S6--><path d="M388.0009,216.5812 C413.0223,216.5812 440.9938,216.5812 464.8352,216.5812 " fill="none" id="S7<-S6" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="382.1489,216.5812,392.9996,221.3667,388.1694,216.564,392.9721,211.7339,382.1489,216.5812" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="40.9398" x="402.1733" y="208.9003">coalesce</text><!--MD5=[630b9631f886cf9c8b0d992525b86cf3]
|
||||||
|
reverse link S8 to S7--><path d="M132.1994,216.5812 C171.0802,216.5812 219.9551,216.5812 257.9689,216.5812 " fill="none" id="S8<-S7" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="126.3836,216.5812,137.2206,221.3977,132.4041,216.5812,137.2206,211.7648,126.3836,216.5812" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="90.3084" x="145.9985" y="208.9003">oversized request</text><!--MD5=[2e2dc33d46c2ffc454d35cea5ea70934]
|
||||||
|
@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 — allocate, fragment, coalesce, verify
|
||||||
|
|
||||||
|
rectangle "01 RESET\ninitial free = 4080" as S1
|
||||||
|
rectangle "02 ALLOC A\n24 byte payload\nfirst-fit + split" as S2
|
||||||
|
rectangle "03 ALLOC B / C\n40 + 16 byte payload\nafter = 3952" as S3
|
||||||
|
rectangle "04 FREE A / C\nB remains allocated" as S4
|
||||||
|
rectangle "05 E01 FRAGMENTED\n2 free blocks\ncurrent > largest" as S5
|
||||||
|
rectangle "06 FREE B\ninsert by address\njoin right + left" as S6
|
||||||
|
rectangle "07 E02 COALESCED\n1 free block\nfinal = initial" as S7
|
||||||
|
rectangle "08 OOM CHECK\nNULL · hook=1\nasserts=0 · PASS=1" as S8
|
||||||
|
|
||||||
|
S1 -right-> S2 : pvPortMalloc
|
||||||
|
S2 -right-> S3 : split remainder
|
||||||
|
S3 -right-> S4 : vPortFree
|
||||||
|
S4 -down-> S5 : heap stats
|
||||||
|
S5 -left-> S6 : continue
|
||||||
|
S6 -left-> S7 : coalesce
|
||||||
|
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 |
|
After Width: | Height: | Size: 25 KiB |
@@ -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 — block state and heap statistics
|
||||||
|
|
||||||
|
[*] --> Free : 01 one list node
|
||||||
|
Free --> Allocated : 02 first-fit + split\ncurrent free decreases
|
||||||
|
Allocated --> Fragmented : free A and C
|
||||||
|
Fragmented : 03 two free blocks
|
||||||
|
Fragmented : sum free > largest block
|
||||||
|
Fragmented --> Coalesced : free B\naddress-order joins neighbours
|
||||||
|
Coalesced : 04 one free block
|
||||||
|
Coalesced : current free = initial free
|
||||||
|
Coalesced --> OOMChecked : request > arena
|
||||||
|
OOMChecked : NULL + hook once
|
||||||
|
OOMChecked --> [*]
|
||||||
|
|
||||||
|
state "05 minimum-ever" as MIN
|
||||||
|
Allocated -right-> MIN : records low watermark
|
||||||
|
Fragmented -right-> MIN : does not rise
|
||||||
|
Coalesced -right-> MIN : history remains
|
||||||
|
@enduml
|
||||||
@@ -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.2823px" preserveAspectRatio="none" style="width:346px;height:600px;" version="1.1" viewBox="0 0 346 600" width="346.9454px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="154.5281" x="99.1803" y="7.9418">A6 STATE — block state and heap statistics</text><ellipse cx="212.8476" cy="23.6993" fill="#000000" rx="7.4292" ry="7.4292" style="stroke: none; stroke-width: 0.742923663722561;"/><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="37.1462" x="194.2745" y="86.8478"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="194.2745" x2="231.4207" y1="104.3956" y2="104.3956"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="15.6014" x="205.0469" y="98.5042">Free</text><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="48.29" x="188.7026" y="190.1142"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="188.7026" x2="236.9926" y1="207.662" y2="207.662"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="33.4316" x="196.1318" y="201.7706">Allocated</text><rect fill="#EDF6FA" height="45.2143" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="101.0376" x="111.0671" y="282.9796"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="111.0671" x2="212.1047" y1="300.5275" y2="300.5275"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="43.0896" x="140.0411" y="294.6361">Fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="65.3773" x="114.7817" y="312.1839">03 two free blocks</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="86.1791" x="114.7817" y="322.3025">sum free > largest block</text><rect fill="#EDF6FA" height="45.2143" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="103.2664" x="4.4575" y="394.3142"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="4.4575" x2="107.7239" y1="411.862" y2="411.862"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="36.4033" x="37.8891" y="405.9706">Coalesced</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="61.6627" x="8.1722" y="423.5185">04 one free block</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="88.4079" x="8.1722" y="433.6371">current free = initial free</text><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="78.7499" x="16.7158" y="495.2478"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="16.7158" x2="95.4657" y1="512.7956" y2="512.7956"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="48.29" x="31.9457" y="506.9042">OOMChecked</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="63.8914" x="20.4304" y="524.4521">NULL + hook once</text><ellipse cx="56.0907" cy="585.1415" fill="none" rx="7.4292" ry="7.4292" style="stroke: #000000; stroke-width: 0.742923663722561;"/><ellipse cx="56.4622" cy="585.513" fill="#000000" rx="4.4575" ry="4.4575" style="stroke: none; stroke-width: 0.742923663722561;"/><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="77.2641" x="190.5599" y="398.3482"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="190.5599" x2="267.824" y1="415.8961" y2="415.8961"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="62.4056" x="197.9892" y="410.0047">05 minimum-ever</text><!--MD5=[f16808fa220dde377303612249059854]
|
||||||
|
link *start to Free--><path d="M212.8476,31.2845 C212.8476,42.3689 212.8476,64.7384 212.8476,81.885 " fill="none" id="*start->Free" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="212.8476,85.4436,215.8193,78.7573,212.8476,81.729,209.8759,78.7573,212.8476,85.4436" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="57.948" x="213.5906" y="62.101">01 one list node</text><!--MD5=[19abaf48dc778410378e95e0d1bca006]
|
||||||
|
link Free to Allocated--><path d="M212.8476,124.358 C212.8476,141.3635 212.8476,166.8235 212.8476,185.1663 " fill="none" id="Free->Allocated" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="212.8476,188.7843,215.8193,182.098,212.8476,185.0697,209.8759,182.098,212.8476,188.7843" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="59.4339" x="224.3629" y="154.9664">02 first-fit + split</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="80.9787" x="213.5906" y="165.085">current free decreases</text><!--MD5=[f6fa3e1917b73de38ea03346a6903b17]
|
||||||
|
link Allocated to Fragmented--><path d="M203.0856,227.6021 C195.3518,241.9925 184.4382,262.304 175.746,278.4849 " fill="none" id="Allocated->Fragmented" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="174.0076,281.7241,179.7784,277.2257,175.7573,278.4473,174.5357,274.4262,174.0076,281.7241" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="43.0896" x="191.028" y="258.2328">free A and C</text><!--MD5=[c73bca393b062d6a86dff80fa900c78c]
|
||||||
|
link Fragmented to Coalesced--><path d="M110.7031,318.744 C93.6455,325.4006 76.1571,335.4523 65.0058,350.4817 C56.8188,361.5141 54.33,376.536 54.0031,389.4331 " fill="none" id="Fragmented->Coalesced" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="53.9808,392.9546,56.9907,386.2854,54.0021,389.24,51.0474,386.2514,53.9808,392.9546" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="21.5448" x="110.6956" y="359.1664">free B</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="111.4385" x="65.7487" y="369.285">address-order joins neighbours</text><!--MD5=[2b306524d92469efb3bb270d490680cf]
|
||||||
|
link Coalesced to OOMChecked--><path d="M56.0907,439.7959 C56.0907,454.8922 56.0907,474.8471 56.0907,490.1216 " fill="none" id="Coalesced->OOMChecked" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="56.0907,493.7842,59.0624,487.0979,56.0907,490.0696,53.119,487.0979,56.0907,493.7842" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="57.2051" x="56.8337" y="470.501">request > arena</text><!--MD5=[6b8be85e17f6174335a5329fe1414850]
|
||||||
|
link OOMChecked to *end--><path d="M56.0907,532.55 C56.0907,545.306 56.0907,562.0366 56.0907,573.0022 " fill="none" id="OOMChecked->*end" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="56.0907,576.4716,59.0624,569.7853,56.0907,572.757,53.119,569.7853,56.0907,576.4716" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><!--MD5=[b09143a670c8c67aa163b99fca5c6b6b]
|
||||||
|
link Allocated to MIN--><path d="M228.8056,227.6169 C233.6049,234.1101 238.3299,241.7622 241.0787,249.548 C259.2432,300.9509 258.5449,318.5879 247.765,372.0264 C246.2941,379.3145 243.5824,386.8998 240.685,393.6827 " fill="none" id="Allocated->MIN" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="239.214,396.9813,244.6551,392.0892,240.7295,393.5899,239.2288,389.6643,239.214,396.9813" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="82.4645" x="256.1378" y="308.6996">records low watermark</text><!--MD5=[1fa23b8554d20d5dd3f2f8930c0e2df3]
|
||||||
|
link Fragmented to MIN--><path d="M172.2766,328.3871 C178.8143,341.366 187.6105,357.9332 196.5033,372.0264 C201.2283,379.5151 206.8225,387.3752 212.0378,394.3513 " fill="none" id="Fragmented->MIN" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="214.2072,397.2338,212.5727,390.1018,211.9784,394.2621,207.818,393.6678,214.2072,397.2338" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="46.8042" x="197.2462" y="364.3669">does not rise</text><!--MD5=[87522a40b34d64237ec6603d41372cd8]
|
||||||
|
link Coalesced to MIN--><path d="M108.0285,416.9213 C132.7679,416.9213 162.0242,416.9213 185.5972,416.9213 " fill="none" id="Coalesced->MIN" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="189.1038,416.9213,182.4175,413.9496,185.3892,416.9213,182.4175,419.893,189.1038,416.9213" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="55.7193" x="121.2823" y="412.2335">history remains</text><!--MD5=[994b73c618d067de5faae1a7c19b4f86]
|
||||||
|
@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 — block state and heap statistics
|
||||||
|
|
||||||
|
[*] - -> Free : 01 one list node
|
||||||
|
Free - -> Allocated : 02 first-fit + split\ncurrent free decreases
|
||||||
|
Allocated - -> Fragmented : free A and C
|
||||||
|
Fragmented : 03 two free blocks
|
||||||
|
Fragmented : sum free > largest block
|
||||||
|
Fragmented - -> Coalesced : free B\naddress-order joins neighbours
|
||||||
|
Coalesced : 04 one free block
|
||||||
|
Coalesced : current free = initial free
|
||||||
|
Coalesced - -> OOMChecked : request > arena
|
||||||
|
OOMChecked : NULL + hook once
|
||||||
|
OOMChecked - -> [*]
|
||||||
|
|
||||||
|
state "05 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: 11 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -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 — one artifact, two checkpoints, one proof
|
||||||
|
|
||||||
|
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
|
||||||
|
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
|
||||||
|
rectangle "<<checkpoint E01>>\n03 fragmented\nblocks=2 · aligned=1" as E1
|
||||||
|
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
|
||||||
|
rectangle "<<checkpoint E02>>\n05 coalesced\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
|
||||||
@@ -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="82.7447px" preserveAspectRatio="none" style="width:814px;height:82px;" version="1.1" viewBox="0 0 814 82" width="814.2079px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="190.3128" x="314.8436" y="7.9609">A7 RUNTIME — one artifact, two checkpoints, one proof</text><!--MD5=[183d75e42a7a852d02a7f9ce2cc3343f]
|
||||||
|
entity SRC--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="78.6075" x="4.9647" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="31.443" x="13.2392" y="38.0453">«source»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="38.89" x="13.2392" y="48.1882">01 task03 C</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="62.0585" x="13.2392" y="58.3311">A/B/C experiment</text><!--MD5=[4a7b087cd571ae358eb895b9dc7ce0ed]
|
||||||
|
entity ELF--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="71.9879" x="181.2109" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="32.2704" x="189.4854" y="38.0453">«artifact»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="51.3017" x="189.4854" y="48.1882">02 ELF + image</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="55.439" x="189.4854" y="58.3311">heap_4 symbols</text><!--MD5=[45565a74ca8123df0b8413ce5340d40a]
|
||||||
|
entity E1--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="86.0545" x="370.6963" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="60.4036" x="378.9707" y="38.0453">«checkpoint E01»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="52.1292" x="378.9707" y="48.1882">03 fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="69.5055" x="378.9707" y="58.3311">blocks=2 · aligned=1</text><!--MD5=[5ceda9279414f57783e95166b8d927b7]
|
||||||
|
entity MEM--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="81.0898" x="553.5621" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="37.2351" x="561.8365" y="38.0453">«memory»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="58.7487" x="561.8365" y="48.1882">04 ucHeap[4096]</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="64.5409" x="561.8365" y="58.3311">headers + payload</text><!--MD5=[a3c437a7ee715155cf6a0fec80d7cbaf]
|
||||||
|
entity E2--><rect fill="#EDF6FA" height="57.1206" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="88.5368" x="716.5691" y="16.7377"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="60.4036" x="724.8436" y="32.9731">«checkpoint E02»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="43.0272" x="724.8436" y="43.116">05 coalesced</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="71.9879" x="724.8436" y="53.2589">final=initial · blocks=1</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="57.0938" x="724.8436" y="63.4018">OOM=1 · PASS=1</text><!--MD5=[2e73c4d4efa4a7715d66b06010e70f85]
|
||||||
|
link SRC to ELF--><path d="M83.961,45.2929 C111.3744,45.2929 148.0054,45.2929 175.7911,45.2929 " fill="none" id="SRC->ELF" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="179.6222,45.2929,172.1752,41.9831,175.485,45.2929,172.1752,48.6027,179.6222,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="46.337" x="109.223" y="42.497">compile + link</text><!--MD5=[98439561a91d683361f6e8599ebb304f]
|
||||||
|
link ELF to E1--><path d="M253.5463,45.2929 C284.8735,45.2929 330.7719,45.2929 365.2765,45.2929 " fill="none" id="ELF->E1" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="369.2482,45.2929,361.8012,41.9831,365.111,45.2929,361.8012,48.6027,369.2482,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="66.1958" x="278.8496" y="42.497">reset / load / replay</text><!--MD5=[14b84038a04448f34eb55bd119f2d935]
|
||||||
|
link E1 to MEM--><path d="M457.1314,45.2929 C484.5447,45.2929 520.1332,45.2929 548.0513,45.2929 " fill="none" id="E1->MEM" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="551.9154,45.2929,544.4684,41.9831,547.7782,45.2929,544.4684,48.6027,551.9154,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="45.5096" x="482.4016" y="42.497">inspect bytes</text><!--MD5=[28f0a5a321106494a7afb95cbc1e35b0]
|
||||||
|
link MEM to E2--><path d="M634.8918,45.2929 C657.8783,45.2929 686.93,45.2929 711.2486,45.2929 " fill="none" id="MEM->E2" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="715.1128,45.2929,707.6658,41.9831,710.9756,45.2929,707.6658,48.6027,715.1128,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="30.6155" x="660.3027" y="42.497">continue</text><!--MD5=[bc1681809f0cb7bb82cdf81f0385b8f2]
|
||||||
|
@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 — one artifact, two checkpoints, one proof
|
||||||
|
|
||||||
|
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
|
||||||
|
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
|
||||||
|
rectangle "<<checkpoint E01>>\n03 fragmented\nblocks=2 · aligned=1" as E1
|
||||||
|
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
|
||||||
|
rectangle "<<checkpoint E02>>\n05 coalesced\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.4 KiB |
@@ -0,0 +1,178 @@
|
|||||||
|
# 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 1–2 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_fragmented_checkpoint`;
|
||||||
|
4. przygotuj widok `ucHeap`, `g_fragmented_stats`, `g_final_stats`,
|
||||||
|
`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 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 0–3 min | problem | Przypomnij wyłącznie offsety `0 -> 5 -> 12`. Uczeń próbuje zwolnić pierwszy obszar bez utraty drugiego i nazywa brakującą operację. |
|
||||||
|
| 3–4 min | kontekst | Jedno zdanie: FreeRTOS dostarcza wymienne implementacje tego samego API; ta karta i oficjalne przykłady Pico 2 W linkują `heap_4`. |
|
||||||
|
| 4–9 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. |
|
||||||
|
| 9–16 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`. |
|
||||||
|
| 16–27 min | Task 3 — RUN | Na przygotowanym Pico 2 W przejdź przez prawdziwy `heap_4.c`: trzy alokacje, free A i C, checkpoint z dwoma blokami, free B, checkpoint z jednym blokiem, OOM=`NULL` i jeden malloc-failed hook. Uczeń wypełnia tabelę relacji. |
|
||||||
|
| 27–30 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(B) == addr(C), połącz B+C;
|
||||||
|
3. jeśli end(A) == addr(BC), połącz A+BC;
|
||||||
|
|
||||||
|
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
|
||||||
|
-> ALLOC A(24)
|
||||||
|
-> ALLOC B(40)
|
||||||
|
-> ALLOC C(16)
|
||||||
|
-> FREE A
|
||||||
|
-> FREE C
|
||||||
|
-> heap4_fragmented_checkpoint # 2 free blocks
|
||||||
|
-> FREE B
|
||||||
|
-> OOM request
|
||||||
|
-> task03_debug_checkpoint # 1 free block, pass=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Uczeń zapisuje tylko relacje, ponieważ dokładne bajty zależą od ABI i
|
||||||
|
konfiguracji:
|
||||||
|
|
||||||
|
| Obserwacja | Oczekiwany związek |
|
||||||
|
| --- | --- |
|
||||||
|
| po trzech alokacjach | `after_allocations < initial_free` |
|
||||||
|
| stan pofragmentowany | `free_blocks == 2`, `largest < total_free` |
|
||||||
|
| po `free(B)` | `final_free == initial_free`, `free_blocks == 1` |
|
||||||
|
| low-water mark | `minimum_ever <= after_allocations` 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 xFreeBytesRemaining
|
||||||
|
p xMinimumEverFreeBytesRemaining
|
||||||
|
p xStart
|
||||||
|
p pxEnd
|
||||||
|
x/96bx ucHeap
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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 1–2 na AMD64 i Hazard3, samodzielny deploy RP2350 oraz
|
||||||
|
porównanie z `heap_1`, `heap_2`, `heap_3` i `heap_5`.
|
||||||
@@ -0,0 +1,312 @@
|
|||||||
|
% 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=0.5cm,headheight=24mm,headsep=3mm,includehead]{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}{M. Pabiszczak}
|
||||||
|
\newcommand{\DocumentYear}{2026}
|
||||||
|
\newcommand{\CardSeries}{freertos-c}
|
||||||
|
\newcommand{\CardNumber}{01}
|
||||||
|
\newcommand{\CardCount}{15}
|
||||||
|
\newcommand{\CardSlug}{heap4-mechanics}
|
||||||
|
\newcommand{\CardVersion}{v00.01}
|
||||||
|
\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 M. 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}
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
\renewcommand{\footrulewidth}{0pt}
|
||||||
|
|
||||||
|
\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 dwa checkpointy 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{0.85cm}>{\ttfamily\raggedright\arraybackslash}p{1.45cm}X>{\raggedright\arraybackslash}p{2.45cm}>{\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
|
||||||
|
\multicolumn{1}{|l|}{\textbf{\texttt{FC01}}} & \multicolumn{1}{l|}{\textbf{\texttt{Task01}}} & \multicolumn{1}{l|}{\textbf{headers, address-ordered free list, first-fit, split, coalescing and heap statistics}} & \multicolumn{1}{l|}{\textbf{główny}} & \multicolumn{1}{l|}{\textbf{opracowane}} & \multicolumn{1}{l|}{\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}
|
||||||
|
\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.44697\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}
|
||||||
|
\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.86277\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}
|
||||||
|
\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.52424\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}
|
||||||
|
\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}
|
||||||
|
\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 rozmiar bloku.}
|
||||||
|
Dodaj nagłówek do 13 bajtów i wyrównaj wynik do ośmiu.
|
||||||
|
\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ąż diagram z dwoma deterministycznymi checkpointami.
|
||||||
|
\begin{ESCStepFrame}{fragmented · Sprawdź E01.}
|
||||||
|
Porównaj liczbę wolnych bloków, największy blok i bieżące wolne bajty.
|
||||||
|
\end{ESCStepFrame}
|
||||||
|
\begin{ESCStepFrame}{coalesced · Sprawdź E02.}
|
||||||
|
Udowodnij pełne scalenie, zachowanie minimum-ever i kontrolowany OOM.
|
||||||
|
\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:} Model 13 -> 32 bajty; poprawna predykcja dwóch wolnych bloków po free(A,C) i jednego po free(B); 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}
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
\documentclass[12pt]{article}
|
\documentclass[10pt]{article}
|
||||||
\usepackage[T1]{fontenc}
|
\usepackage[T1]{fontenc}
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
\usepackage[polish]{babel}
|
\usepackage[polish]{babel}
|
||||||
\usepackage[a4paper,margin=2.0cm]{geometry}
|
\usepackage[a4paper,margin=1.55cm]{geometry}
|
||||||
\usepackage{array}
|
\usepackage{array,tabularx,booktabs}
|
||||||
\usepackage{tabularx}
|
\usepackage{amsmath,amssymb}
|
||||||
\usepackage{xcolor}
|
\usepackage{xcolor,listings}
|
||||||
\usepackage{listings}
|
\usepackage{hyperref,fancyhdr,lastpage}
|
||||||
\usepackage{hyperref}
|
|
||||||
\usepackage{fancyhdr}
|
|
||||||
\usepackage{lastpage}
|
|
||||||
\usepackage{enumitem}
|
\usepackage{enumitem}
|
||||||
|
|
||||||
\definecolor{accent}{HTML}{16324A}
|
\definecolor{accent}{HTML}{16324A}
|
||||||
\definecolor{accentlight}{HTML}{EEF3F7}
|
\definecolor{accentlight}{HTML}{EEF3F7}
|
||||||
\definecolor{rulegray}{HTML}{D7DEE5}
|
\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}}
|
\IfFileExists{build-meta.tex}{\input{build-meta.tex}}{\newcommand{\BuildCommit}{local}}
|
||||||
\newcommand{\PublisherDomain}{mpabi}
|
\newcommand{\PublisherDomain}{mpabi}
|
||||||
\newcommand{\DocumentAuthor}{M. Pabiszczak}
|
\newcommand{\DocumentAuthor}{M. Pabiszczak}
|
||||||
@@ -23,236 +21,286 @@
|
|||||||
\newcommand{\CardArea}{inf}
|
\newcommand{\CardArea}{inf}
|
||||||
\newcommand{\CardSeries}{rv32i-freertos}
|
\newcommand{\CardSeries}{rv32i-freertos}
|
||||||
\newcommand{\CardNumber}{01}
|
\newcommand{\CardNumber}{01}
|
||||||
\newcommand{\CardCount}{??}
|
\newcommand{\CardCount}{15}
|
||||||
\newcommand{\CardSlug}{heap4}
|
\newcommand{\CardSlug}{heap4}
|
||||||
\newcommand{\CardVersion}{v0.1}
|
\newcommand{\CardVersion}{v0.3}
|
||||||
\newcommand{\DocumentKey}{\PublisherDomain/\CardArea/\CardSeries/\CardNumber/\CardSlug/\CardVersion}
|
\newcommand{\DocumentKey}{\PublisherDomain/\CardArea/\CardSeries/\CardNumber/\CardSlug/\CardVersion}
|
||||||
\newcommand{\DocumentUUID}{4654524c-73f2-46df-83a3-d448ba6d6c5a}
|
\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}
|
\pagestyle{fancy}
|
||||||
\fancyhf{}
|
\fancyhf{}
|
||||||
\lhead{\textbf{FreeRTOS: heap\_4}}
|
\lhead{\textbf{FC01 · FreeRTOS \texttt{heap\_4}}}
|
||||||
\rhead{\small \DocumentAuthor, \DocumentYear}
|
\rhead{\small 30 minut · Pico 2 W / RP2350}
|
||||||
\lfoot{\scriptsize commit \BuildCommit}
|
\lfoot{\scriptsize commit \BuildCommit}
|
||||||
\cfoot{\scriptsize \thepage/\pageref{LastPage}}
|
\cfoot{\scriptsize \thepage/\pageref{LastPage}}
|
||||||
\rfoot{\scriptsize uuid \DocumentUUID}
|
\rfoot{\scriptsize V11.3.0 / \CardVersion}
|
||||||
\renewcommand{\headrulewidth}{0.4pt}
|
\setlength{\headheight}{14pt}
|
||||||
\setlength{\headheight}{18pt}
|
\setlength{\footskip}{19pt}
|
||||||
\setlength{\footskip}{24pt}
|
\setlist[itemize]{nosep,leftmargin=1.45em}
|
||||||
|
\setlist[enumerate]{nosep,leftmargin=1.65em}
|
||||||
|
\newcommand{\checkline}{\(\square\)\;}
|
||||||
|
\newcommand{\blank}[1]{\rule{#1}{.2pt}}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
\sloppy
|
\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}
|
\begin{center}
|
||||||
\noindent\rule{\textwidth}{0.5pt}
|
{\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}
|
\noindent\begin{tabularx}{\textwidth}{@{}p{1.45cm}Xp{1.4cm}X@{}}
|
||||||
Ta karta zaczyna serię FreeRTOS od \texttt{heap\_4}, ponieważ ten plik jest
|
\toprule
|
||||||
naturalnym pomostem po kartach z języka C. Wymaga wskaźników, tablic,
|
Karta & FC01 / \CardCount & Czas & 30 minut \\
|
||||||
struktur, listy jednokierunkowej, \texttt{static}, \texttt{typedef}, makr oraz
|
Płytka & Raspberry Pi Pico 2 W & Układ & RP2350, rdzeń RISC-V \\
|
||||||
arytmetyki adresów, ale nie wymaga jeszcze schedulera, przerwań ani
|
Allocator & FreeRTOS-Kernel V11.3.0 & Źródło & upstream \texttt{heap\_4.c} \\
|
||||||
uruchamiania tasków.
|
Wersja & \CardVersion & Data & 19.07.2026 \\
|
||||||
|
\bottomrule
|
||||||
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
|
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
|
|
||||||
\TaskSection{01}{task01_heap_map}{mapa \texttt{heap\_4}}{
|
\section*{Punkt startowy — tego już nie powtarzamy}
|
||||||
\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{Polecenia}
|
Z poprzedniej karty działa projekt:
|
||||||
\begin{enumerate}[leftmargin=1.6em]
|
|
||||||
\item Zbuduj kartę dla RV32I poleceniem \texttt{make tasks}.
|
\begin{lstlisting}
|
||||||
\item Zbuduj wariant hostowy poleceniem \texttt{make host}; wypisywanie działa tylko przez \texttt{HOST\_PRINTF}.
|
allocbuf[64]; allocp = allocbuf;
|
||||||
\item W tasku 6 zmień próg \texttt{MIN\_SPLIT\_SIZE} i sprawdź, kiedy blok nie jest dzielony.
|
alloc_local(5) -> offset 0
|
||||||
\item W tasku 8 zmień rozmiary bloków tak, aby scalanie działało tylko z prawym sąsiadem.
|
alloc_local(7) -> offset 5
|
||||||
\item W tasku 10 dodaj większą alokację, która ma się nie udać, i zapisz status w nowej zmiennej \texttt{volatile}.
|
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 & dwa checkpointy prawdziwego \texttt{heap\_4.c} na Pico 2 W \\
|
||||||
|
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}
|
\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. To jest mechanizm funkcji
|
||||||
|
\texttt{prvInsertBlockIntoFreeList()} z \texttt{heap\_4.c}.
|
||||||
|
|
||||||
|
\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
|
||||||
|
-> ALLOC A(24) -> ALLOC B(40) -> ALLOC C(16)
|
||||||
|
-> FREE A -> FREE C
|
||||||
|
-> heap4_fragmented_checkpoint # STOP 1
|
||||||
|
-> FREE B -> OOM request
|
||||||
|
-> task03_debug_checkpoint # STOP 2
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\textbf{STOP 1:} zapisz liczbę bloków, sumę i largest. Przed \texttt{F5}
|
||||||
|
przewidź, co zmieni \texttt{FREE B}.
|
||||||
|
|
||||||
|
\textbf{STOP 2:} sprawdź 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 xFreeBytesRemaining
|
||||||
|
p xMinimumEverFreeBytesRemaining
|
||||||
|
p xStart
|
||||||
|
p pxEnd
|
||||||
|
x/96bx 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 \\
|
||||||
|
STOP 1: free blocks & \blank{2.3cm} & równe 2 \\
|
||||||
|
STOP 1: total / largest & \blank{2.3cm} & largest mniejsze niż total \\
|
||||||
|
STOP 2: final free & \blank{2.3cm} & równe initial \\
|
||||||
|
STOP 2: 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}
|
\end{document}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e69aaa6d61af39003186415f3581d519e7a290bd
|
48eccb5e2497b692892c7b24ffa1ed7a6f8480b8
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
# K01 `heap4` — punkt zatrzymania
|
||||||
|
|
||||||
|
## Stan repozytorium
|
||||||
|
|
||||||
|
- Data: `2026-07-14`.
|
||||||
|
- Commit bazowy: `8aee0b104c4f6e6ffef119ab6f57a3e724144221`.
|
||||||
|
- Gałąź robocza: `work/list-first-rp2350-debug`.
|
||||||
|
- Zmienione źródła: brak.
|
||||||
|
- Zmieniona karta PDF: brak.
|
||||||
|
- Lokalny stan `.stem/`: wygenerowany przez testy `stemctl`, nie jest częścią karty.
|
||||||
|
- Review Claude: nieukończony; dwie sesje CLI nie zwróciły wyniku i zostały zatrzymane.
|
||||||
|
|
||||||
|
## Potwierdzone
|
||||||
|
|
||||||
|
- [x] `make host` buduje 10/10 programów.
|
||||||
|
- [x] Wszystkie programy hostowe uruchamiają się z kodem `0`.
|
||||||
|
- [x] `make tasks RV_ENV_ROOT=...` buduje 10/10 ELF dla RV32I.
|
||||||
|
- [x] `stemctl test native-amd64 freertos heap4 10` przechodzi.
|
||||||
|
- [x] RP2350 Probe jest wykrywany bez `sudo` po wejściu do grupy `rpdebug`.
|
||||||
|
- [x] OpenOCD wykrywa `rp2350.rv0` i `rp2350.rv1`.
|
||||||
|
- [x] Oba rdzenie raportują `XLEN=32`.
|
||||||
|
- [ ] Nie wykonano testu programu K01 na RTL Hazard3.
|
||||||
|
- [ ] Nie wgrano programu K01 na fizyczny RP2350.
|
||||||
|
|
||||||
|
## Wyniki bazowe — host AMD64
|
||||||
|
|
||||||
|
| Task | Wynik |
|
||||||
|
|---|---|
|
||||||
|
| 01 | `header=16 aligned=16 allocated=1 total=32 user=16` |
|
||||||
|
| 02 | `free=136 largest=80 count=3` |
|
||||||
|
| 03 | `offset=0 free=144 end_last=1` |
|
||||||
|
| 04 | `r1=24 r9=32 r17=40 delta=7` |
|
||||||
|
| 05 | `ok=1 allocated=120 remaining=0` |
|
||||||
|
| 06 | `allocated=48 split=128 nodes=1` |
|
||||||
|
| 07 | `order=1 count=3 total=120` |
|
||||||
|
| 08 | `count=1 size=160 merged_right=1` |
|
||||||
|
| 09 | `heap=256 adjusted=248 dynamic=1 host_trace=1` |
|
||||||
|
| 10 | `ok=1 nodes=1 free=240 min=144` |
|
||||||
|
|
||||||
|
## Braki P0
|
||||||
|
|
||||||
|
- [ ] Dodać `stem-card.yaml`.
|
||||||
|
- [ ] Obsłużyć targety:
|
||||||
|
- [ ] `native` / `native-amd64`;
|
||||||
|
- [ ] `hazard3-baremetal` / `hazard3-sim`;
|
||||||
|
- [ ] `rp2350-rv` / fizyczny Hazard3.
|
||||||
|
- [ ] Naprawić `stemctl test hazard3-sim freertos heap4 10`.
|
||||||
|
- Stan obecny: `Legacy Hazard3 card/task is unsupported`.
|
||||||
|
- [ ] Dodać asercje wyniku.
|
||||||
|
- Stan obecny: każdy `main()` zwraca `0` niezależnie od wartości `g_*`.
|
||||||
|
- [ ] Dodać automatyczne porównanie wyników AMD64 i RV32.
|
||||||
|
- [ ] Dodać bezpieczne sprawdzanie przepełnienia rozmiaru żądania.
|
||||||
|
- [ ] Sprawdzić wyrównanie buforów używanych jako `HeapBlock`.
|
||||||
|
- [ ] Nie dereferencjonować wyniku alokacji przed sprawdzeniem `p != NULL`.
|
||||||
|
|
||||||
|
## Braki debug
|
||||||
|
|
||||||
|
- [ ] K10: dodać jawne checkpointy:
|
||||||
|
- [ ] `INIT`;
|
||||||
|
- [ ] `ALLOC_A`;
|
||||||
|
- [ ] `ALLOC_B`;
|
||||||
|
- [ ] `FREE_A`;
|
||||||
|
- [ ] `ALLOC_C`;
|
||||||
|
- [ ] `ALLOC_REJECTED`;
|
||||||
|
- [ ] `FREE_B`;
|
||||||
|
- [ ] `FREE_C`;
|
||||||
|
- [ ] `DONE`.
|
||||||
|
- [ ] K10: zapisywać przy checkpointcie:
|
||||||
|
- [ ] numer zdarzenia;
|
||||||
|
- [ ] adres bloku;
|
||||||
|
- [ ] liczbę wolnych bloków;
|
||||||
|
- [ ] sumę wolnej pamięci;
|
||||||
|
- [ ] minimum wolnej pamięci;
|
||||||
|
- [ ] status `RUNNING/PASS/FAIL`.
|
||||||
|
- [ ] Simulator:
|
||||||
|
- [ ] breakpoint na funkcji checkpointu;
|
||||||
|
- [ ] inspekcja listy i pamięci;
|
||||||
|
- [ ] bez obiecywania watchpointów — szybki stub obsługuje obecnie breakpointy wykonania.
|
||||||
|
- [ ] RP2350:
|
||||||
|
- [ ] OpenOCD `target/rp2350-riscv.cfg`;
|
||||||
|
- [ ] breakpoint `main`;
|
||||||
|
- [ ] sprzętowy watchpoint na numerze zdarzenia/statusie;
|
||||||
|
- [ ] porównanie adresów i wyników z symulatorem;
|
||||||
|
- [ ] Termdebug i DAP na tym samym ELF.
|
||||||
|
|
||||||
|
## Braki materiału
|
||||||
|
|
||||||
|
- [ ] Zmniejszyć udział prozy.
|
||||||
|
- [ ] Zastąpić akapity:
|
||||||
|
- [ ] listami kontrolnymi;
|
||||||
|
- [ ] tabelami wartości;
|
||||||
|
- [ ] komendami do skopiowania;
|
||||||
|
- [ ] punktami zatrzymania GDB;
|
||||||
|
- [ ] kryteriami zaliczenia.
|
||||||
|
- [ ] Szablon każdego taska:
|
||||||
|
- [ ] `Cel` — maksymalnie 3 punkty;
|
||||||
|
- [ ] `Uruchom` — komendy;
|
||||||
|
- [ ] `Zatrzymaj` — breakpoint/watchpoint;
|
||||||
|
- [ ] `Obserwuj` — symbole i pamięć;
|
||||||
|
- [ ] `Oczekuj` — wartości host/RV32;
|
||||||
|
- [ ] `Zmień` — jeden eksperyment;
|
||||||
|
- [ ] `Zaliczenie` — mierzalna checklista.
|
||||||
|
- [ ] Przenieść pełne listingi C/ASM do dodatku.
|
||||||
|
- [ ] Pierwsze strony PDF przeznaczyć na kartę prowadzącego i przebieg lekcji.
|
||||||
|
|
||||||
|
## Kolejność wznowienia K01
|
||||||
|
|
||||||
|
1. Zamknąć wymagania w bezpośrednim poprzedniku `inf/structures`.
|
||||||
|
2. Dodać testy wyniku do K01.
|
||||||
|
3. Dodać kontrakt `stem-card.yaml`.
|
||||||
|
4. Uruchomić 10/10 tasków na Hazard3 RTL.
|
||||||
|
5. Dodać checkpointy K10.
|
||||||
|
6. Zbudować K10 dla `rp2350-rv`.
|
||||||
|
7. Wgrać i debugować K10 przez JTAG.
|
||||||
|
8. Przebudować README/PDF do formatu list-first.
|
||||||
|
9. Wykonać końcowy review techniczny i dydaktyczny.
|
||||||
|
|
||||||
|
## Bezpośredni poprzednik
|
||||||
|
|
||||||
|
- Seria: `inf`.
|
||||||
|
- Karta: `structures`.
|
||||||
|
- Repozytorium: `lab-rv32i-c-structures`.
|
||||||
|
- Przejście wymagane przed K01:
|
||||||
|
- [ ] `struct` i `typedef`;
|
||||||
|
- [ ] struktura samoreferencyjna;
|
||||||
|
- [ ] pole `next`;
|
||||||
|
- [ ] przejście po liście;
|
||||||
|
- [ ] wstawianie elementu;
|
||||||
|
- [ ] wartownik;
|
||||||
|
- [ ] `sizeof`, padding i wyrównanie na AMD64/RV32;
|
||||||
|
- [ ] niezmienniki listy;
|
||||||
|
- [ ] obserwacja w GDB.
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef HEAP4_FREESTANDING_STDLIB_H
|
||||||
|
#define HEAP4_FREESTANDING_STDLIB_H
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,811 @@
|
|||||||
|
{
|
||||||
|
"card": {
|
||||||
|
"number": "01",
|
||||||
|
"slug": "heap4-mechanics",
|
||||||
|
"title": "heap_4: From Linear Cursor to Reusable Blocks",
|
||||||
|
"topic": "headers, address-ordered free list, first-fit, split, coalescing and heap statistics",
|
||||||
|
"status": "Gotowa",
|
||||||
|
"version": "v00.01",
|
||||||
|
"revision_date": "2026-07-20T00:00:00+02:00"
|
||||||
|
},
|
||||||
|
"front": {
|
||||||
|
"goal": "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.",
|
||||||
|
"scope": "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."
|
||||||
|
},
|
||||||
|
"viewpoints": [
|
||||||
|
{
|
||||||
|
"id": "A1",
|
||||||
|
"label": "CONTEXT",
|
||||||
|
"subtitle": "from cursor to reusable heap",
|
||||||
|
"status": "enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A2",
|
||||||
|
"label": "STRUCTURE",
|
||||||
|
"subtitle": "headers and address order",
|
||||||
|
"status": "enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A3",
|
||||||
|
"label": "DISPATCH",
|
||||||
|
"subtitle": "not used by the allocator",
|
||||||
|
"status": "unavailable",
|
||||||
|
"reason": "heap_4 is called directly through pvPortMalloc and vPortFree; there is no callback or dispatch mechanism to explain."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A4",
|
||||||
|
"label": "APPLICATION",
|
||||||
|
"subtitle": "experiment is already explicit",
|
||||||
|
"status": "unavailable",
|
||||||
|
"reason": "The concrete A/B/C allocation experiment is completely represented by A5 and its two runtime checkpoints."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A5",
|
||||||
|
"label": "FLOW",
|
||||||
|
"subtitle": "allocate, fragment, coalesce",
|
||||||
|
"status": "enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A6",
|
||||||
|
"label": "STATE",
|
||||||
|
"subtitle": "block list and statistics",
|
||||||
|
"status": "enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A7",
|
||||||
|
"label": "RUNTIME",
|
||||||
|
"subtitle": "Hazard3 evidence",
|
||||||
|
"status": "enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A8",
|
||||||
|
"label": "PATTERNS",
|
||||||
|
"subtitle": "mechanism, not a separate page",
|
||||||
|
"status": "unavailable",
|
||||||
|
"reason": "First-fit and the intrusive address-ordered free list are already proved in A2 and A5; a separate pattern page would duplicate them."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"artifact": {
|
||||||
|
"source": "src/tasks/task03_freertos_heap4.c",
|
||||||
|
"elf": "build/task03_freertos_heap4/prog.elf",
|
||||||
|
"image": "build/task03_freertos_heap4/prog.bin"
|
||||||
|
},
|
||||||
|
"strategies": [
|
||||||
|
{
|
||||||
|
"id": "code.model",
|
||||||
|
"kind": "code",
|
||||||
|
"prerequisites": [
|
||||||
|
"K&R 5.4 linear allocator complete"
|
||||||
|
],
|
||||||
|
"layout": [
|
||||||
|
"header",
|
||||||
|
"payload",
|
||||||
|
"remainder",
|
||||||
|
"address-ordered list"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
"rg -n 'ModelBlock|align_up|insert_and_coalesce' src/tasks"
|
||||||
|
],
|
||||||
|
"expected_observations": [
|
||||||
|
"requested size includes header and alignment",
|
||||||
|
"free list is ordered by block address"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"payload begins after the header",
|
||||||
|
"split preserves the total arena size"
|
||||||
|
],
|
||||||
|
"evidence_fields": [
|
||||||
|
"code_ref",
|
||||||
|
"header bytes",
|
||||||
|
"wanted bytes",
|
||||||
|
"block address"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "code.heap4",
|
||||||
|
"kind": "code",
|
||||||
|
"prerequisites": [
|
||||||
|
"FreeRTOS-Kernel V11.3.0 available"
|
||||||
|
],
|
||||||
|
"layout": [
|
||||||
|
"ucHeap",
|
||||||
|
"BlockLink_t",
|
||||||
|
"xStart",
|
||||||
|
"pxEnd"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
"rg -n 'BlockLink_t|prvInsertBlockIntoFreeList|pvPortMalloc|vPortFree' vendor/FreeRTOS-Kernel/portable/MemMang/heap_4.c"
|
||||||
|
],
|
||||||
|
"expected_observations": [
|
||||||
|
"heap_4 keeps metadata inside the arena",
|
||||||
|
"free blocks form one address-ordered intrusive list"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"allocated bit is stored in the size field",
|
||||||
|
"xStart and pxEnd are sentinels"
|
||||||
|
],
|
||||||
|
"evidence_fields": [
|
||||||
|
"symbol",
|
||||||
|
"list link",
|
||||||
|
"block size",
|
||||||
|
"arena address"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "run.fragmented",
|
||||||
|
"kind": "run",
|
||||||
|
"prerequisites": [
|
||||||
|
"clean Hazard3 RAM",
|
||||||
|
"task03 image loaded"
|
||||||
|
],
|
||||||
|
"layout": [
|
||||||
|
"source",
|
||||||
|
"free-list stats",
|
||||||
|
"ucHeap memory",
|
||||||
|
"registers"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
"break heap4_fragmented_checkpoint",
|
||||||
|
"print g_fragmented_stats",
|
||||||
|
"x/64bx ucHeap"
|
||||||
|
],
|
||||||
|
"expected_observations": [
|
||||||
|
"A and C are free while B remains allocated",
|
||||||
|
"the free list contains two blocks"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"xNumberOfFreeBlocks equals 2",
|
||||||
|
"current free bytes exceed the largest free block"
|
||||||
|
],
|
||||||
|
"evidence_fields": [
|
||||||
|
"free blocks",
|
||||||
|
"largest block",
|
||||||
|
"free bytes",
|
||||||
|
"heap bytes"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "run.coalesced",
|
||||||
|
"kind": "run",
|
||||||
|
"prerequisites": [
|
||||||
|
"fragmented checkpoint reached"
|
||||||
|
],
|
||||||
|
"layout": [
|
||||||
|
"final stats",
|
||||||
|
"minimum-ever",
|
||||||
|
"OOM hook",
|
||||||
|
"PASS"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
"break task03_debug_checkpoint",
|
||||||
|
"print g_final_stats",
|
||||||
|
"print g_task03_pass"
|
||||||
|
],
|
||||||
|
"expected_observations": [
|
||||||
|
"freeing B joins both neighbours",
|
||||||
|
"the arena returns to one reusable block"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"final free equals initial free",
|
||||||
|
"minimum-ever does not rise after free",
|
||||||
|
"oversized allocation returns NULL and calls the hook once"
|
||||||
|
],
|
||||||
|
"evidence_fields": [
|
||||||
|
"final free",
|
||||||
|
"largest block",
|
||||||
|
"minimum-ever",
|
||||||
|
"OOM hook",
|
||||||
|
"PASS"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "code.identity",
|
||||||
|
"kind": "code",
|
||||||
|
"prerequisites": [
|
||||||
|
"built ELF"
|
||||||
|
],
|
||||||
|
"layout": [
|
||||||
|
"symbols",
|
||||||
|
"sections",
|
||||||
|
"artifact hashes"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
"tests/check_task03_elf.sh build/task03_freertos_heap4/prog.elf"
|
||||||
|
],
|
||||||
|
"expected_observations": [
|
||||||
|
"upstream heap_4 symbols are linked",
|
||||||
|
"checkpoint and ucHeap symbols remain observable"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"pvPortMalloc and vPortFree are present",
|
||||||
|
"prvInsertBlockIntoFreeList is present"
|
||||||
|
],
|
||||||
|
"evidence_fields": [
|
||||||
|
"source blob",
|
||||||
|
"ELF SHA256",
|
||||||
|
"image SHA256",
|
||||||
|
"symbol"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checkpoints": {
|
||||||
|
"task01.fragmented": {
|
||||||
|
"event_id": "E01",
|
||||||
|
"stop": {
|
||||||
|
"symbol": "heap4_fragmented_checkpoint",
|
||||||
|
"offset": 0
|
||||||
|
},
|
||||||
|
"verify": {
|
||||||
|
"expressions": [
|
||||||
|
{
|
||||||
|
"expr": "g_fragmented_stats.xNumberOfFreeBlocks",
|
||||||
|
"equals": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "g_initial_free > g_after_allocations",
|
||||||
|
"equals": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "g_allocations_aligned",
|
||||||
|
"equals": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"task01.coalesced": {
|
||||||
|
"event_id": "E02",
|
||||||
|
"stop": {
|
||||||
|
"symbol": "task03_debug_checkpoint",
|
||||||
|
"offset": 0
|
||||||
|
},
|
||||||
|
"verify": {
|
||||||
|
"expressions": [
|
||||||
|
{
|
||||||
|
"expr": "g_final_stats.xNumberOfFreeBlocks",
|
||||||
|
"equals": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "g_final_free == g_initial_free",
|
||||||
|
"equals": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "g_oom_is_null",
|
||||||
|
"equals": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"expr": "g_task03_pass",
|
||||||
|
"equals": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "A1",
|
||||||
|
"label": "CONTEXT",
|
||||||
|
"title": "Od liniowego kursora do odzyskiwalnej areny",
|
||||||
|
"order": 10,
|
||||||
|
"orientation": "portrait",
|
||||||
|
"description": "Aplikacja korzysta z publicznego API, heap_4 zarządza jedną areną, a Hazard3 pokazuje jej rzeczywisty stan.",
|
||||||
|
"content_tex": "Kursor liniowy potrafi tylko rosnąć. heap_4 dodaje metadane i listę wolnych bloków, dzięki czemu zwolniona pamięć wraca do ponownego użycia.",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"stem": "a1-context",
|
||||||
|
"title": "A1 · granice odpowiedzialności heap_4",
|
||||||
|
"caption": "A1 CONTEXT — od żądania aplikacji do rzeczywistych bajtów ucHeap.",
|
||||||
|
"label": "fig:a1-context",
|
||||||
|
"alt": "A1 · granice odpowiedzialności heap_4",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"id": "boundary",
|
||||||
|
"label": "APPLICATION / API / ALLOCATOR / TARGET",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "application",
|
||||||
|
"number": 1,
|
||||||
|
"label": "aplikacja żąda i zwalnia bajty",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "01",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:78",
|
||||||
|
"description": "Aplikacja zna wyłącznie publiczne API i wskaźniki payloadu.",
|
||||||
|
"evidence": "trzy żądania 24, 40 i 16 bajtów"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api",
|
||||||
|
"number": 2,
|
||||||
|
"label": "FreeRTOS wystawia malloc, free i statystyki",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "02",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:90",
|
||||||
|
"description": "API oddziela eksperyment od prywatnej listy bloków.",
|
||||||
|
"evidence": "pvPortMalloc, vPortFree, vPortGetHeapStats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "allocator",
|
||||||
|
"number": 3,
|
||||||
|
"label": "heap_4 zarządza blokami i kolejnością adresów",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "03",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:70",
|
||||||
|
"description": "Prywatny mechanizm wybiera, dzieli i scala wolne bloki.",
|
||||||
|
"evidence": "reset i inicjalizacja listy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "arena",
|
||||||
|
"number": 4,
|
||||||
|
"label": "ucHeap jest jedną ograniczoną areną",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "04",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:11",
|
||||||
|
"description": "Metadane i payload znajdują się w tej samej statycznej tablicy.",
|
||||||
|
"evidence": "4096 bajtów, wyrównanie portu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "target",
|
||||||
|
"number": 5,
|
||||||
|
"label": "Hazard3 ujawnia adresy i bajty",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.identity",
|
||||||
|
"svg_label": "05",
|
||||||
|
"code_ref": "tests/check_task03_elf.sh:8",
|
||||||
|
"description": "ELF łączy kod, symbole i pamięć obserwowaną przez GDB.",
|
||||||
|
"evidence": "ucHeap i checkpointy w symbolach ELF"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A2",
|
||||||
|
"label": "STRUCTURE",
|
||||||
|
"title": "Nagłówek, payload i lista wolnych bloków",
|
||||||
|
"order": 20,
|
||||||
|
"orientation": "portrait",
|
||||||
|
"description": "Każdy blok ma nagłówek, a tylko wolne bloki wykorzystują wskaźnik next do budowy listy uporządkowanej adresami.",
|
||||||
|
"content_tex": "Rozmiar żądania rośnie o nagłówek i wyrównanie. Duży wolny blok może zostać rozdzielony na blok przydzielony i użyteczną resztę.",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"stem": "a2-structure",
|
||||||
|
"title": "A2 · struktura bloku i listy",
|
||||||
|
"caption": "A2 STRUCTURE — metadane wewnątrz areny i adresowo uporządkowana lista.",
|
||||||
|
"label": "fig:a2-structure",
|
||||||
|
"alt": "A2 · struktura bloku i listy",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"id": "blocks",
|
||||||
|
"label": "HEADER / PAYLOAD / FREE LIST",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "header",
|
||||||
|
"number": 1,
|
||||||
|
"label": "nagłówek przechowuje next i size",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.model",
|
||||||
|
"svg_label": "01",
|
||||||
|
"code_ref": "src/tasks/heap4_model.h:11",
|
||||||
|
"description": "ModelBlock pokazuje minimalny kontrakt metadanych heap_4.",
|
||||||
|
"evidence": "dwa słowa metadanych"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "alignment",
|
||||||
|
"number": 2,
|
||||||
|
"label": "żądanie obejmuje nagłówek i wyrównanie",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.model",
|
||||||
|
"svg_label": "02",
|
||||||
|
"code_ref": "src/tasks/task01_first_fit_split.c:3",
|
||||||
|
"description": "13 bajtów payloadu zajmuje 32 bajty całego bloku.",
|
||||||
|
"evidence": "header=16, wanted=32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "split",
|
||||||
|
"number": 3,
|
||||||
|
"label": "split pozostawia osobny wolny blok",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.model",
|
||||||
|
"svg_label": "03",
|
||||||
|
"code_ref": "src/tasks/task01_first_fit_split.c:43",
|
||||||
|
"description": "Reszta zachowuje własny nagłówek i trafia na listę wolnych.",
|
||||||
|
"evidence": "32 + 224 = 256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "address-order",
|
||||||
|
"number": 4,
|
||||||
|
"label": "lista jest uporządkowana rosnącymi adresami",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.model",
|
||||||
|
"svg_label": "04",
|
||||||
|
"code_ref": "src/tasks/task02_address_order_coalesce.c:29",
|
||||||
|
"description": "Pozycja w liście ujawnia bezpośredniego poprzednika i następnika.",
|
||||||
|
"evidence": "previous < block < current"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "right-join",
|
||||||
|
"number": 5,
|
||||||
|
"label": "blok scala się z prawym sąsiadem",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.model",
|
||||||
|
"svg_label": "05",
|
||||||
|
"code_ref": "src/tasks/task02_address_order_coalesce.c:40",
|
||||||
|
"description": "Koniec zwalnianego bloku równy adresowi current oznacza ciągłość.",
|
||||||
|
"evidence": "block + size == current"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "left-join",
|
||||||
|
"number": 6,
|
||||||
|
"label": "wynik scala się z lewym sąsiadem",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.model",
|
||||||
|
"svg_label": "06",
|
||||||
|
"code_ref": "src/tasks/task02_address_order_coalesce.c:48",
|
||||||
|
"description": "Drugi test domyka dwustronne scalanie w jeden blok.",
|
||||||
|
"evidence": "previous + size == block"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A5",
|
||||||
|
"label": "FLOW",
|
||||||
|
"title": "First-fit, fragmentacja i pełne scalenie",
|
||||||
|
"order": 50,
|
||||||
|
"orientation": "landscape",
|
||||||
|
"description": "Jeden przebieg A/B/C przechodzi od pustej areny przez trzy przydziały i dwa wolne obszary do ponownie scalonego bloku.",
|
||||||
|
"content_tex": "Uczeń najpierw przewiduje liczbę wolnych bloków. RUN odtwarza dwa stabilne stany: po zwolnieniu A i C oraz po zwolnieniu B.",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"stem": "a5-flow",
|
||||||
|
"title": "A5 · pełny przebieg heap_4",
|
||||||
|
"caption": "A5 FLOW — inicjalizacja, A/B/C, fragmentacja, dwustronne scalenie i OOM.",
|
||||||
|
"label": "fig:a5-flow",
|
||||||
|
"alt": "A5 · pełny przebieg heap_4",
|
||||||
|
"diagram_kind": "sequence",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"id": "replay",
|
||||||
|
"label": "ALLOCATE / FRAGMENT / COALESCE",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "reset",
|
||||||
|
"number": 1,
|
||||||
|
"label": "reset i inicjalizacja areny",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "01",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:70",
|
||||||
|
"description": "Pierwsze małe żądanie inicjalizuje sentinele i listę.",
|
||||||
|
"evidence": "initial free = 4080"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "alloc-a",
|
||||||
|
"number": 2,
|
||||||
|
"label": "first-fit przydziela A",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "02",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:78",
|
||||||
|
"description": "Pierwszy wystarczający blok zostaje rozdzielony.",
|
||||||
|
"evidence": "A payload = 24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "alloc-bc",
|
||||||
|
"number": 3,
|
||||||
|
"label": "kolejne split tworzą B i C",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "03",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:79",
|
||||||
|
"description": "B i C zajmują kolejne fragmenty tego samego wolnego bloku.",
|
||||||
|
"evidence": "after allocations = 3952"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "free-ac",
|
||||||
|
"number": 4,
|
||||||
|
"label": "zwolnij A i C, pozostaw B",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "04",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:88",
|
||||||
|
"description": "C scala się z prawą resztą, ale B oddziela ją od A.",
|
||||||
|
"evidence": "dwa wolne bloki"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fragmented",
|
||||||
|
"number": 5,
|
||||||
|
"label": "checkpoint fragmentacji",
|
||||||
|
"mode": "RUN",
|
||||||
|
"event_id": "E01",
|
||||||
|
"strategy_ref": "run.fragmented",
|
||||||
|
"svg_label": "05",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:91",
|
||||||
|
"snapshot_ref": "task01.fragmented",
|
||||||
|
"description": "GDB zatrzymuje program przy dwóch wolnych blokach.",
|
||||||
|
"evidence": "xNumberOfFreeBlocks = 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "free-b",
|
||||||
|
"number": 6,
|
||||||
|
"label": "zwolnij B między dwoma sąsiadami",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "06",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:93",
|
||||||
|
"description": "Wstawienie adresowe umożliwia dwa testy ciągłości.",
|
||||||
|
"evidence": "A + B + C + reszta są ciągłe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coalesced",
|
||||||
|
"number": 7,
|
||||||
|
"label": "arena wraca do jednego bloku",
|
||||||
|
"mode": "RUN",
|
||||||
|
"event_id": "E02",
|
||||||
|
"strategy_ref": "run.coalesced",
|
||||||
|
"svg_label": "07",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:96",
|
||||||
|
"snapshot_ref": "task01.coalesced",
|
||||||
|
"description": "Finalne statystyki dowodzą pełnego odzyskania areny.",
|
||||||
|
"evidence": "final free = initial free; blocks = 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "oom",
|
||||||
|
"number": 8,
|
||||||
|
"label": "zbyt duże żądanie kończy się NULL",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "08",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:98",
|
||||||
|
"description": "Kontrolowany OOM nie narusza listy i wywołuje hook dokładnie raz.",
|
||||||
|
"evidence": "NULL, hooks=1, asserts=0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A6",
|
||||||
|
"label": "STATE",
|
||||||
|
"title": "Stan bloku a stan statystyk",
|
||||||
|
"order": 60,
|
||||||
|
"orientation": "portrait",
|
||||||
|
"description": "Bieżąca liczba wolnych bajtów może rosnąć po free, ale minimum-ever pozostaje historycznym minimum.",
|
||||||
|
"content_tex": "Fragmentacja to nie tylko suma wolnych bajtów. O możliwości przydziału decyduje także największy pojedynczy blok.",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"stem": "a6-state",
|
||||||
|
"title": "A6 · stany bloków i liczników",
|
||||||
|
"caption": "A6 STATE — wolny, przydzielony, rozdzielony, scalony oraz minimum-ever.",
|
||||||
|
"label": "fig:a6-state",
|
||||||
|
"alt": "A6 · stany bloków i liczników",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"id": "state",
|
||||||
|
"label": "BLOCK STATE / HEAP STATS",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "free",
|
||||||
|
"number": 1,
|
||||||
|
"label": "wolny blok należy do listy",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "01",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:70",
|
||||||
|
"description": "Stan początkowy zawiera jeden największy wolny blok.",
|
||||||
|
"evidence": "initial free = largest free"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "allocated",
|
||||||
|
"number": 2,
|
||||||
|
"label": "przydzielony blok znika z listy wolnych",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "02",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:78",
|
||||||
|
"description": "Payload jest wyrównany, a bieżąca wolna pamięć maleje.",
|
||||||
|
"evidence": "all payload pointers aligned"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fragmented-state",
|
||||||
|
"number": 3,
|
||||||
|
"label": "dwa wolne bloki nie są jednym dużym blokiem",
|
||||||
|
"mode": "RUN",
|
||||||
|
"event_id": "E01",
|
||||||
|
"strategy_ref": "run.fragmented",
|
||||||
|
"svg_label": "03",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:90",
|
||||||
|
"snapshot_ref": "task01.fragmented",
|
||||||
|
"description": "Suma wolnego miejsca nie gwarantuje jednego dużego przydziału.",
|
||||||
|
"evidence": "free blocks = 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coalesced-state",
|
||||||
|
"number": 4,
|
||||||
|
"label": "scalenie przywraca jeden największy blok",
|
||||||
|
"mode": "RUN",
|
||||||
|
"event_id": "E02",
|
||||||
|
"strategy_ref": "run.coalesced",
|
||||||
|
"svg_label": "04",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:94",
|
||||||
|
"snapshot_ref": "task01.coalesced",
|
||||||
|
"description": "Current free i largest wracają do wartości początkowej.",
|
||||||
|
"evidence": "free blocks = 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "minimum-ever",
|
||||||
|
"number": 5,
|
||||||
|
"label": "minimum-ever zachowuje najniższy poziom",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "05",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:95",
|
||||||
|
"description": "Historyczne minimum nie zwiększa się po odzyskaniu pamięci.",
|
||||||
|
"evidence": "minimum-ever <= after allocations"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "A7",
|
||||||
|
"label": "RUNTIME",
|
||||||
|
"title": "Dowód w Hazard3 i ELF",
|
||||||
|
"order": 70,
|
||||||
|
"orientation": "landscape",
|
||||||
|
"description": "Ten sam artefakt łączy źródło, symbole ELF, dwa checkpointy, pamięć ucHeap i końcowe asercje.",
|
||||||
|
"content_tex": "Snapshot jest dowodem tylko wtedy, gdy zawiera tożsamość artefaktu, pozycję programu i wartości, które rozstrzygają hipotezę.",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"stem": "a7-runtime",
|
||||||
|
"title": "A7 · dowód runtime heap_4",
|
||||||
|
"caption": "A7 RUNTIME — kod, ELF, checkpoint, pamięć i statystyki jednego przebiegu.",
|
||||||
|
"label": "fig:a7-runtime",
|
||||||
|
"alt": "A7 · dowód runtime heap_4",
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"id": "evidence",
|
||||||
|
"label": "ARTIFACT / CHECKPOINT / MEMORY / ASSERTION",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "source",
|
||||||
|
"number": 1,
|
||||||
|
"label": "źródło wskazuje eksperyment A/B/C",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.identity",
|
||||||
|
"svg_label": "01",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:62",
|
||||||
|
"description": "Blob źródła jest częścią tożsamości karty.",
|
||||||
|
"evidence": "source git blob"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "elf",
|
||||||
|
"number": 2,
|
||||||
|
"label": "ELF zawiera prawdziwe symbole heap_4",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.identity",
|
||||||
|
"svg_label": "02",
|
||||||
|
"code_ref": "tests/check_task03_elf.sh:8",
|
||||||
|
"description": "Test ABI odrzuca atrapę bez pvPortMalloc, vPortFree i ucHeap.",
|
||||||
|
"evidence": "upstream symbols present"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fragmented-runtime",
|
||||||
|
"number": 3,
|
||||||
|
"label": "checkpoint pokazuje dwa wolne bloki",
|
||||||
|
"mode": "RUN",
|
||||||
|
"event_id": "E01",
|
||||||
|
"strategy_ref": "run.fragmented",
|
||||||
|
"svg_label": "03",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:91",
|
||||||
|
"snapshot_ref": "task01.fragmented",
|
||||||
|
"description": "Neovim, GDB i pamięć zatrzymują się na tym samym stanie.",
|
||||||
|
"evidence": "blocks=2 and aligned=1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "memory",
|
||||||
|
"number": 4,
|
||||||
|
"label": "ucHeap ujawnia nagłówki i payload",
|
||||||
|
"mode": "CODE",
|
||||||
|
"strategy_ref": "code.heap4",
|
||||||
|
"svg_label": "04",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:11",
|
||||||
|
"description": "Widok bajtów łączy diagram z realnym układem areny.",
|
||||||
|
"evidence": "aligned arena and in-band metadata"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "final-runtime",
|
||||||
|
"number": 5,
|
||||||
|
"label": "checkpoint końcowy dowodzi odzyskania",
|
||||||
|
"mode": "RUN",
|
||||||
|
"event_id": "E02",
|
||||||
|
"strategy_ref": "run.coalesced",
|
||||||
|
"svg_label": "05",
|
||||||
|
"code_ref": "src/tasks/task03_freertos_heap4.c:111",
|
||||||
|
"snapshot_ref": "task01.coalesced",
|
||||||
|
"description": "Jedna ramka łączy stats, OOM, hook i PASS.",
|
||||||
|
"evidence": "final=initial, blocks=1, pass=1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"learning": {
|
||||||
|
"model_label": "Model bloków heap_4",
|
||||||
|
"model": "Uczeń wyjaśnia nagłówek, wyrównanie, first-fit, split, adresową listę wolnych bloków i dwustronne coalescing.",
|
||||||
|
"replay_label": "Fragmentacja i odzyskanie areny",
|
||||||
|
"replay": "Uczeń odtwarza dwa checkpointy Hazard3 i odróżnia current free, largest free block oraz minimum-ever.",
|
||||||
|
"criterion": "Model 13 -> 32 bajty; poprawna predykcja dwóch wolnych bloków po free(A,C) i jednego po free(B); final free = initial free; minimum-ever nie rośnie; OOM zwraca NULL; PASS=1.",
|
||||||
|
"requirement": "Analiza i weryfikacja mechaniki dynamicznej alokacji heap_4 w FreeRTOS C na RV32I/Hazard3."
|
||||||
|
},
|
||||||
|
"task": {
|
||||||
|
"short_label": "mechanika heap_4",
|
||||||
|
"title": "Predict and prove reusable heap_4 blocks",
|
||||||
|
"prompt_tex": "Przewidź układ bloków po alloc A/B/C, następnie po free(A,C) i free(B). Odtwórz oba checkpointy i udowodnij, że arena została scalona bez utraty minimum-ever.",
|
||||||
|
"conclusion_tex": "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.",
|
||||||
|
"flow": [
|
||||||
|
{
|
||||||
|
"kind": "block",
|
||||||
|
"id": "predict",
|
||||||
|
"title": "A — przewidywanie",
|
||||||
|
"content_tex": "Przejdź przez model nagłówka, split i porządek adresowy przed uruchomieniem prawdziwego heap\\_4.",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "size",
|
||||||
|
"title": "Policz rozmiar bloku.",
|
||||||
|
"content_tex": "Dodaj nagłówek do 13 bajtów i wyrównaj wynik do ośmiu."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "list",
|
||||||
|
"title": "Narysuj listę po free(A,C).",
|
||||||
|
"content_tex": "Zaznacz, dlaczego przydzielony B rozdziela dwa wolne obszary."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "block",
|
||||||
|
"id": "replay",
|
||||||
|
"title": "B — replay Hazard3",
|
||||||
|
"content_tex": "Powiąż diagram z dwoma deterministycznymi checkpointami.",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "fragmented",
|
||||||
|
"title": "Sprawdź E01.",
|
||||||
|
"content_tex": "Porównaj liczbę wolnych bloków, największy blok i bieżące wolne bajty."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "coalesced",
|
||||||
|
"title": "Sprawdź E02.",
|
||||||
|
"content_tex": "Udowodnij pełne scalenie, zachowanie minimum-ever i kontrolowany OOM."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "exercise",
|
||||||
|
"id": "fragmentation",
|
||||||
|
"title": "Ćwiczenie — ta sama suma, inna użyteczność",
|
||||||
|
"prompt_tex": "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.",
|
||||||
|
"evidence_tex": "Dwa diagramy listy, suma wolnych bajtów, rozmiar największego bloku i wynik pvPortMalloc.",
|
||||||
|
"criterion": "Uczeń nie utożsamia sumy wolnej pamięci z możliwością pojedynczego dużego przydziału.",
|
||||||
|
"based_on": [
|
||||||
|
"predict",
|
||||||
|
"replay"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
#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_fragmented_stats;
|
||||||
|
HeapStats_t g_final_stats;
|
||||||
|
volatile size_t g_initial_free;
|
||||||
|
volatile size_t g_after_allocations;
|
||||||
|
volatile size_t g_final_free;
|
||||||
|
volatile size_t g_minimum_ever_free;
|
||||||
|
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_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_fragmented_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)
|
||||||
|
{
|
||||||
|
void *probe;
|
||||||
|
void *a;
|
||||||
|
void *b;
|
||||||
|
void *c;
|
||||||
|
void *too_large;
|
||||||
|
|
||||||
|
vPortHeapResetState();
|
||||||
|
probe = pvPortMalloc(1U);
|
||||||
|
if (probe != NULL)
|
||||||
|
{
|
||||||
|
vPortFree(probe);
|
||||||
|
}
|
||||||
|
g_initial_free = xPortGetFreeHeapSize();
|
||||||
|
|
||||||
|
a = pvPortMalloc(24U);
|
||||||
|
b = pvPortMalloc(40U);
|
||||||
|
c = pvPortMalloc(16U);
|
||||||
|
g_after_allocations = xPortGetFreeHeapSize();
|
||||||
|
g_allocations_aligned =
|
||||||
|
a != NULL && b != NULL && c != NULL &&
|
||||||
|
((uintptr_t)a % portBYTE_ALIGNMENT) == 0U &&
|
||||||
|
((uintptr_t)b % portBYTE_ALIGNMENT) == 0U &&
|
||||||
|
((uintptr_t)c % portBYTE_ALIGNMENT) == 0U;
|
||||||
|
|
||||||
|
vPortFree(a);
|
||||||
|
vPortFree(c);
|
||||||
|
vPortGetHeapStats(&g_fragmented_stats);
|
||||||
|
heap4_fragmented_checkpoint();
|
||||||
|
|
||||||
|
vPortFree(b);
|
||||||
|
g_final_free = xPortGetFreeHeapSize();
|
||||||
|
g_minimum_ever_free = xPortGetMinimumEverFreeHeapSize();
|
||||||
|
vPortGetHeapStats(&g_final_stats);
|
||||||
|
|
||||||
|
too_large = pvPortMalloc(configTOTAL_HEAP_SIZE * 2U);
|
||||||
|
g_oom_is_null = too_large == NULL;
|
||||||
|
g_task03_pass =
|
||||||
|
probe != NULL && g_allocations_aligned &&
|
||||||
|
g_initial_free > g_after_allocations &&
|
||||||
|
g_final_free == g_initial_free &&
|
||||||
|
g_minimum_ever_free <= g_after_allocations &&
|
||||||
|
g_fragmented_stats.xNumberOfFreeBlocks == 2U &&
|
||||||
|
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=%zu fragmented=%zu final=%zu min=%zu "
|
||||||
|
"aligned=%d oom=%d hooks=%d asserts=%d pass=%d\n",
|
||||||
|
g_initial_free, g_after_allocations,
|
||||||
|
g_fragmented_stats.xNumberOfFreeBlocks, g_final_free,
|
||||||
|
g_minimum_ever_free, g_allocations_aligned, g_oom_is_null,
|
||||||
|
g_malloc_failed_hooks, g_assert_failures, g_task03_pass);
|
||||||
|
#endif
|
||||||
|
return g_task03_pass ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/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_fragmented_checkpoint task03_debug_checkpoint 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 observable checkpoints: %s\n' "$elf"
|
||||||
@@ -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=3952 fragmented=2 final=4080 min=3952 aligned=1 oom=1 hooks=1 asserts=0 pass=1'
|
||||||
@@ -0,0 +1,358 @@
|
|||||||
|
#!/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 [[ -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"
|
||||||
|
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_fragmented_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
|
||||||
@@ -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
|
||||||
@@ -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->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->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->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->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 |
@@ -0,0 +1,48 @@
|
|||||||
|
@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 — in-band metadata and address order
|
||||||
|
|
||||||
|
class "01 Block header" as HEADER {
|
||||||
|
next : BlockLink_t*
|
||||||
|
size : size_t
|
||||||
|
}
|
||||||
|
class "Allocated block" as ALLOC {
|
||||||
|
02 header + 13 byte request
|
||||||
|
aligned total = 32 bytes
|
||||||
|
payload begins after header
|
||||||
|
}
|
||||||
|
class "03 Free remainder" as REM {
|
||||||
|
own header
|
||||||
|
size = 224 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADER *-- ALLOC : precedes payload
|
||||||
|
ALLOC -down-> REM : split preserves 256
|
||||||
|
|
||||||
|
class "04 Address-ordered free list" as LIST {
|
||||||
|
previous < inserted < current
|
||||||
|
}
|
||||||
|
class "05 Right neighbour" as RIGHT {
|
||||||
|
block + block.size == current
|
||||||
|
}
|
||||||
|
class "06 Left neighbour" as LEFT {
|
||||||
|
previous + previous.size == block
|
||||||
|
}
|
||||||
|
|
||||||
|
REM -down-> LIST : insert by address
|
||||||
|
LIST -down-> RIGHT : join first
|
||||||
|
RIGHT -down-> LEFT : then join left
|
||||||
|
|
||||||
|
note right of LIST
|
||||||
|
Ordering makes both physical
|
||||||
|
neighbours locally visible.
|
||||||
|
end note
|
||||||
|
@enduml
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?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.2921px" preserveAspectRatio="none" style="width:295px;height:620px;" version="1.1" viewBox="0 0 295 620" width="295.9262px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="202.1522" x="49.1929" y="8.2167">A2 STRUCTURE — in-band metadata and address order</text><!--MD5=[9827fb78ff6e3f59cfadf959dc26af7c]
|
||||||
|
class HEADER--><rect fill="#EDF6FA" height="54.7579" id="HEADER" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="81.4758" x="29.5926" y="16.4642"/><ellipse cx="39.5849" cy="27.2252" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M40.5698,29.7593 Q40.3055,29.8914 40.0173,29.9515 Q39.7291,30.0235 39.4048,30.0235 Q38.2758,30.0235 37.6753,29.2789 Q37.0869,28.5343 37.0869,27.1171 Q37.0869,25.6999 37.6753,24.9553 Q38.2758,24.2107 39.4048,24.2107 Q39.7291,24.2107 40.0173,24.2828 Q40.3175,24.3428 40.5698,24.4749 L40.5698,25.7119 Q40.2815,25.4477 40.0053,25.3276 Q39.7411,25.2075 39.4648,25.2075 Q38.8523,25.2075 38.5401,25.6879 Q38.2278,26.1683 38.2278,27.1171 Q38.2278,28.0659 38.5401,28.5463 Q38.8523,29.0267 39.4648,29.0267 Q39.7411,29.0267 40.0053,28.9066 Q40.2815,28.7865 40.5698,28.5223 L40.5698,29.7593 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="59.9539" x="48.8086" y="30.2075">01 Block header</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="30.3613" x2="110.2998" y1="37.9862" y2="37.9862"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="68.4089" x="34.2045" y="49.2775">next : BlockLink_t*</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="42.2752" x="34.2045" y="59.7463">size : size_t</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="30.3613" x2="110.2998" y1="65.073" y2="65.073"/><!--MD5=[40d637119be40bcfdc4ce848efbdda9e]
|
||||||
|
class ALLOC--><rect fill="#EDF6FA" height="65.2267" id="ALLOC" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="114.5273" x="13.0669" y="128.8701"/><ellipse cx="39.6618" cy="139.631" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M40.6466,142.1652 Q40.3824,142.2973 40.0942,142.3573 Q39.8059,142.4294 39.4816,142.4294 Q38.3527,142.4294 37.7522,141.6848 Q37.1637,140.9401 37.1637,139.523 Q37.1637,138.1058 37.7522,137.3612 Q38.3527,136.6165 39.4816,136.6165 Q39.8059,136.6165 40.0942,136.6886 Q40.3944,136.7486 40.6466,136.8808 L40.6466,138.1178 Q40.3584,137.8536 40.0821,137.7335 Q39.8179,137.6134 39.5417,137.6134 Q38.9292,137.6134 38.6169,138.0938 Q38.3047,138.5742 38.3047,139.523 Q38.3047,140.4717 38.6169,140.9521 Q38.9292,141.4325 39.5417,141.4325 Q39.8179,141.4325 40.0821,141.3124 Q40.3584,141.1923 40.6466,140.9281 L40.6466,142.1652 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="56.1107" x="52.5749" y="142.6134">Allocated block</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="150.392" y2="150.392"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="105.3036" x="17.6787" y="161.6833">02 header + 13 byte request</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="88.3935" x="17.6787" y="172.1522">aligned total = 32 bytes</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="104.535" x="17.6787" y="182.621">payload begins after header</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="187.9477" y2="187.9477"/><!--MD5=[71c2adef9be32489055f250a531e7c6f]
|
||||||
|
class REM--><rect fill="#EDF6FA" height="54.7579" id="REM" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="89.9308" x="25.3651" y="251.7448"/><ellipse cx="35.3574" cy="262.5058" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M36.3422,265.0399 Q36.078,265.172 35.7898,265.232 Q35.5015,265.3041 35.1773,265.3041 Q34.0483,265.3041 33.4478,264.5595 Q32.8593,263.8148 32.8593,262.3977 Q32.8593,260.9805 33.4478,260.2359 Q34.0483,259.4913 35.1773,259.4913 Q35.5015,259.4913 35.7898,259.5633 Q36.09,259.6234 36.3422,259.7555 L36.3422,260.9925 Q36.054,260.7283 35.7778,260.6082 Q35.5135,260.4881 35.2373,260.4881 Q34.6248,260.4881 34.3125,260.9685 Q34.0003,261.4489 34.0003,262.3977 Q34.0003,263.3465 34.3125,263.8269 Q34.6248,264.3073 35.2373,264.3073 Q35.5135,264.3073 35.7778,264.1872 Q36.054,264.0671 36.3422,263.8028 L36.3422,265.0399 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="68.4089" x="44.5811" y="265.4881">03 Free remainder</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="26.1337" x2="114.5273" y1="273.2667" y2="273.2667"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="43.8125" x="29.9769" y="284.558">own header</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="59.9539" x="29.9769" y="295.0269">size = 224 bytes</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="26.1337" x2="114.5273" y1="300.3535" y2="300.3535"/><!--MD5=[b0a0edd67d9eafaaa5639bbe6382adce]
|
||||||
|
class LIST--><rect fill="#EDF6FA" height="44.289" id="LIST" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="124.5196" x="8.0707" y="364.1506"/><ellipse cx="18.063" cy="374.9116" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M19.0478,377.4457 Q18.7836,377.5778 18.4954,377.6379 Q18.2071,377.7099 17.8829,377.7099 Q16.7539,377.7099 16.1534,376.9653 Q15.565,376.2207 15.565,374.8035 Q15.565,373.3863 16.1534,372.6417 Q16.7539,371.8971 17.8829,371.8971 Q18.2071,371.8971 18.4954,371.9692 Q18.7956,372.0292 19.0478,372.1613 L19.0478,373.3983 Q18.7596,373.1341 18.4834,373.014 Q18.2192,372.8939 17.9429,372.8939 Q17.3304,372.8939 17.0182,373.3743 Q16.7059,373.8547 16.7059,374.8035 Q16.7059,375.7523 17.0182,376.2327 Q17.3304,376.7131 17.9429,376.7131 Q18.2192,376.7131 18.4834,376.593 Q18.7596,376.4729 19.0478,376.2087 L19.0478,377.4457 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="102.9977" x="27.2867" y="377.8939">04 Address-ordered free list</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="8.8394" x2="131.8217" y1="385.6726" y2="385.6726"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="107.6095" x="12.6826" y="396.9639">previous < inserted < current</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="8.8394" x2="131.8217" y1="402.2905" y2="402.2905"/><!--MD5=[490fcd32b6546c9bc615869efabd094a]
|
||||||
|
class RIGHT--><rect fill="#EDF6FA" height="44.289" id="RIGHT" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="114.5273" x="13.0669" y="466.0876"/><ellipse cx="33.0899" cy="476.8486" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M34.0748,479.3827 Q33.8105,479.5148 33.5223,479.5748 Q33.2341,479.6469 32.9098,479.6469 Q31.7808,479.6469 31.1803,478.9023 Q30.5919,478.1577 30.5919,476.7405 Q30.5919,475.3233 31.1803,474.5787 Q31.7808,473.8341 32.9098,473.8341 Q33.2341,473.8341 33.5223,473.9061 Q33.8225,473.9662 34.0748,474.0983 L34.0748,475.3353 Q33.7865,475.0711 33.5103,474.951 Q33.2461,474.8309 32.9698,474.8309 Q32.3573,474.8309 32.0451,475.3113 Q31.7328,475.7917 31.7328,476.7405 Q31.7328,477.6893 32.0451,478.1697 Q32.3573,478.6501 32.9698,478.6501 Q33.2461,478.6501 33.5103,478.53 Q33.7865,478.4099 34.0748,478.1457 L34.0748,479.3827 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="70.7148" x="44.5427" y="479.8309">05 Right neighbour</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="487.6095" y2="487.6095"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="105.3036" x="17.6787" y="498.9008">block + block.size == current</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="13.8355" x2="126.8255" y1="504.2275" y2="504.2275"/><!--MD5=[007d3a1820cefd008c8dbdad7e6fdec6]
|
||||||
|
class LEFT--><rect fill="#EDF6FA" height="44.289" id="LEFT" style="stroke: #2C7794; stroke-width: 1.1529592799906587;" width="131.4374" x="4.6118" y="568.0246"/><ellipse cx="34.7809" cy="578.7855" fill="#ADD1B2" rx="6.9178" ry="6.9178" style="stroke: #2C7794; stroke-width: 0.7686395199937726;"/><path d="M35.7658,581.3197 Q35.5015,581.4518 35.2133,581.5118 Q34.9251,581.5839 34.6008,581.5839 Q33.4718,581.5839 32.8713,580.8393 Q32.2829,580.0946 32.2829,578.6775 Q32.2829,577.2603 32.8713,576.5157 Q33.4718,575.771 34.6008,575.771 Q34.9251,575.771 35.2133,575.8431 Q35.5135,575.9032 35.7658,576.0353 L35.7658,577.2723 Q35.4775,577.0081 35.2013,576.888 Q34.9371,576.7679 34.6608,576.7679 Q34.0483,576.7679 33.7361,577.2483 Q33.4238,577.7287 33.4238,578.6775 Q33.4238,579.6262 33.7361,580.1066 Q34.0483,580.587 34.6608,580.587 Q34.9371,580.587 35.2013,580.4669 Q35.4775,580.3468 35.7658,580.0826 L35.7658,581.3197 Z "/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="65.3344" x="48.2321" y="581.7679">06 Left neighbour</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="5.3805" x2="135.2806" y1="589.5465" y2="589.5465"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="122.2137" x="9.2237" y="600.8378">previous + previous.size == block</text><line style="stroke: #2C7794; stroke-width: 1.1529592799906587;" x1="5.3805" x2="135.2806" y1="606.1645" y2="606.1645"/><path d="M159.877,371.9831 L159.877,383.2206 L132.7671,386.2952 L159.877,389.3697 L159.877,400.6072 A0,0 0 0 0 159.877,400.6072 L286.7025,400.6072 A0,0 0 0 0 286.7025,400.6072 L286.7025,379.6695 L279.0161,371.9831 L159.877,371.9831 A0,0 0 0 0 159.877,371.9831 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7686395199937726;"/><path d="M279.0161,371.9831 L279.0161,379.6695 L286.7025,379.6695 L279.0161,371.9831 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="110.6841" x="164.4889" y="384.043">Ordering makes both physical</text><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="96.0799" x="164.4889" y="394.5119">neighbours locally visible.</text><!--MD5=[fc2657b7de304bb41a5d36ac60748945]
|
||||||
|
reverse link HEADER to ALLOC--><path d="M70.3305,82.6749 C70.3305,97.5173 70.3305,114.3505 70.3305,128.5626 " fill="none" id="HEADER<-ALLOC" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,72.7056,67.256,77.3174,70.3305,81.9293,73.4051,77.3174,70.3305,72.7056" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="65.3344" x="71.0992" y="103.2667">precedes payload</text><!--MD5=[bb73b5a7e21afff1a1d0c43dcbd5d11a]
|
||||||
|
link ALLOC to REM--><path d="M70.3305,194.2813 C70.3305,210.5842 70.3305,230.3382 70.3305,246.6026 " fill="none" id="ALLOC->REM" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,250.3689,73.4051,243.4512,70.3305,246.5257,67.256,243.4512,70.3305,250.3689" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="70.7148" x="71.0992" y="226.1414">split preserves 256</text><!--MD5=[32aec76f28e14f88b0d74d9f592c80fb]
|
||||||
|
link REM to LIST--><path d="M70.3305,306.8178 C70.3305,322.8901 70.3305,343.1975 70.3305,359.1622 " fill="none" id="REM->LIST" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,362.8055,73.4051,355.8878,70.3305,358.9623,67.256,355.8878,70.3305,362.8055" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="63.7971" x="71.0992" y="338.5473">insert by address</text><!--MD5=[6bd3103bbaa36e7d502940b82c286473]
|
||||||
|
link LIST to RIGHT--><path d="M70.3305,408.6011 C70.3305,423.9508 70.3305,444.681 70.3305,461.0377 " fill="none" id="LIST->RIGHT" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,464.7963,73.4051,457.8786,70.3305,460.9531,67.256,457.8786,70.3305,464.7963" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="30.7456" x="71.0992" y="440.4842">join first</text><!--MD5=[f41c07ebada6943a8deaf240fd528885]
|
||||||
|
link RIGHT to LEFT--><path d="M70.3305,510.538 C70.3305,525.8878 70.3305,546.618 70.3305,562.9746 " fill="none" id="RIGHT->LEFT" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><polygon fill="#8095A1" points="70.3305,566.7333,73.4051,559.8155,70.3305,562.8901,67.256,559.8155,70.3305,566.7333" style="stroke: #8095A1; stroke-width: 0.7686395199937726;"/><text fill="#000000" font-family="Monospace" font-size="7.6864" lengthAdjust="spacingAndGlyphs" textLength="47.6557" x="71.0992" y="542.4212">then join left</text><!--MD5=[83344144544ae5f259c61315a4ceaf0d]
|
||||||
|
@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 — in-band metadata and address order
|
||||||
|
|
||||||
|
class "01 Block header" as HEADER {
|
||||||
|
next : BlockLink_t*
|
||||||
|
size : size_t
|
||||||
|
}
|
||||||
|
class "Allocated block" as ALLOC {
|
||||||
|
02 header + 13 byte request
|
||||||
|
aligned total = 32 bytes
|
||||||
|
payload begins after header
|
||||||
|
}
|
||||||
|
class "03 Free remainder" as REM {
|
||||||
|
own header
|
||||||
|
size = 224 bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADER *- - ALLOC : precedes payload
|
||||||
|
ALLOC -down-> REM : split preserves 256
|
||||||
|
|
||||||
|
class "04 Address-ordered free list" as LIST {
|
||||||
|
previous < inserted < current
|
||||||
|
}
|
||||||
|
class "05 Right neighbour" as RIGHT {
|
||||||
|
block + block.size == current
|
||||||
|
}
|
||||||
|
class "06 Left neighbour" as LEFT {
|
||||||
|
previous + previous.size == block
|
||||||
|
}
|
||||||
|
|
||||||
|
REM -down-> LIST : insert by address
|
||||||
|
LIST -down-> RIGHT : join first
|
||||||
|
RIGHT -down-> LEFT : then join left
|
||||||
|
|
||||||
|
note right of LIST
|
||||||
|
Ordering makes both physical
|
||||||
|
neighbours locally visible.
|
||||||
|
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: 15 KiB |
@@ -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 — allocate, fragment, coalesce, verify
|
||||||
|
|
||||||
|
rectangle "01 RESET\ninitial free = 4080" as S1
|
||||||
|
rectangle "02 ALLOC A\n24 byte payload\nfirst-fit + split" as S2
|
||||||
|
rectangle "03 ALLOC B / C\n40 + 16 byte payload\nafter = 3952" as S3
|
||||||
|
rectangle "04 FREE A / C\nB remains allocated" as S4
|
||||||
|
rectangle "05 E01 FRAGMENTED\n2 free blocks\ncurrent > largest" as S5
|
||||||
|
rectangle "06 FREE B\ninsert by address\njoin right + left" as S6
|
||||||
|
rectangle "07 E02 COALESCED\n1 free block\nfinal = initial" as S7
|
||||||
|
rectangle "08 OOM CHECK\nNULL · hook=1\nasserts=0 · PASS=1" as S8
|
||||||
|
|
||||||
|
S1 -right-> S2 : pvPortMalloc
|
||||||
|
S2 -right-> S3 : split remainder
|
||||||
|
S3 -right-> S4 : vPortFree
|
||||||
|
S4 -down-> S5 : heap stats
|
||||||
|
S5 -left-> S6 : continue
|
||||||
|
S6 -left-> S7 : coalesce
|
||||||
|
S7 -left-> S8 : oversized request
|
||||||
|
@enduml
|
||||||
@@ -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="263.7004px" preserveAspectRatio="none" style="width:811px;height:263px;" version="1.1" viewBox="0 0 811 263" width="811.5712px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="231.1894" x="294.4053" y="11.5848">A5 FLOW — allocate, fragment, coalesce, verify</text><!--MD5=[d0cae5ff9305becd6f502d4fe4f41481]
|
||||||
|
entity S1--><rect fill="#EDF6FA" height="53.6024" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="108.37" x="7.2247" y="32.316"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="45.7562" x="19.2658" y="55.942">01 RESET</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="84.2878" x="19.2658" y="70.7021">initial free = 4080</text><!--MD5=[d3395af3100fe8cebf35265100c4415f]
|
||||||
|
entity S2--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="104.7577" x="224.5668" y="24.9348"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="59.0015" x="236.6079" y="48.5608">02 ALLOC A</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="80.6755" x="236.6079" y="63.3209">24 byte payload</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="63.8179" x="236.6079" y="78.081">first-fit + split</text><!--MD5=[6c7192638421eaf134d201765ac5db29]
|
||||||
|
entity S3--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="127.6358" x="450.3377" y="24.9348"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="74.6549" x="462.3789" y="48.5608">03 ALLOC B / C</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="103.5536" x="462.3789" y="63.3209">40 + 16 byte payload</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="59.0015" x="462.3789" y="78.081">after = 3952</text><!--MD5=[01b905ebe31ca24275b86a9951c478d0]
|
||||||
|
entity S4--><rect fill="#EDF6FA" height="53.6024" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="121.6153" x="671.2922" y="32.316"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="65.022" x="683.3333" y="55.942">04 FREE A / C</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="97.533" x="683.3333" y="70.7021">B remains allocated</text><!--MD5=[099bd2cf1f4f3a6dbf2f1fde6174f38e]
|
||||||
|
entity S5--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="132.4523" x="665.8737" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="108.37" x="677.9148" y="206.0345">05 E01 FRAGMENTED</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="62.6138" x="677.9148" y="220.7946">2 free blocks</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="84.2878" x="677.9148" y="235.5547">current > largest</text><!--MD5=[0656c7721b015b9ca8cf2e2c2e8f5aee]
|
||||||
|
entity S6--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="111.9824" x="465.3891" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="49.3686" x="477.4302" y="206.0345">06 FREE B</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="87.9001" x="477.4302" y="220.7946">insert by address</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="72.2467" x="477.4302" y="235.5547">join right + left</text><!--MD5=[6ba532df225878998c5769132c3837e2]
|
||||||
|
entity S7--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="121.6153" x="258.2819" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="97.533" x="270.3231" y="206.0345">07 E02 COALESCED</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="57.7974" x="270.3231" y="220.7946">1 free block</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="59.0015" x="270.3231" y="235.5547">final = initial</text><!--MD5=[ce611cd767df6ac8a45071985dabb378]
|
||||||
|
entity S8--><rect fill="#EDF6FA" height="68.3625" style="stroke: #2C7794; stroke-width: 1.8061674008810573;" width="115.5947" x="8.4288" y="182.4086"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="79.4714" x="20.4699" y="206.0345">08 OOM CHECK</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="73.4508" x="20.4699" y="220.7946">NULL · hook=1</text><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="91.5125" x="20.4699" y="235.5547">asserts=0 · PASS=1</text><!--MD5=[15cb110786dd224ca6a510a3d2a24e20]
|
||||||
|
link S1 to S2--><path d="M115.7994,59.1196 C146.5043,59.1196 184.9515,59.1196 216.5956,59.1196 " fill="none" id="S1->S2" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="222.2429,59.1196,211.4059,54.3031,216.2223,59.1196,211.4059,63.936,222.2429,59.1196" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="65.022" x="137.5698" y="51.4386">pvPortMalloc</text><!--MD5=[8eac89d31ced3c9003fbd6a8a005c745]
|
||||||
|
link S2 to S3--><path d="M329.5894,59.1196 C362.7266,59.1196 405.9181,59.1196 442.1979,59.1196 " fill="none" id="S2->S3" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="448.0018,59.1196,437.1648,54.3031,441.9812,59.1196,437.1648,63.936,448.0018,59.1196" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="77.0631" x="351.2996" y="51.4386">split remainder</text><!--MD5=[82e284a09e4ebade00512bdc77bff32c]
|
||||||
|
link S3 to S4--><path d="M578.3709,59.1196 C605.1142,59.1196 636.2044,59.1196 663.4053,59.1196 " fill="none" id="S3->S4" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="669.1369,59.1196,658.2999,54.3031,663.1163,59.1196,658.2999,63.936,669.1369,59.1196" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="49.3686" x="599.9486" y="51.4386">vPortFree</text><!--MD5=[0e6b031b378ab8978eaa734a548bdfb6]
|
||||||
|
link S4 to S5--><path d="M732.0999,86.2723 C732.0999,110.3906 732.0999,146.6826 732.0999,174.6541 " fill="none" id="S4->S5" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="732.0999,180.494,736.9163,169.657,732.0999,174.4735,727.2834,169.657,732.0999,180.494" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="51.7768" x="733.304" y="142.2166">heap stats</text><!--MD5=[3c9aaad44b43c509ca535c241fdd0151]
|
||||||
|
reverse link S6 to S5--><path d="M585.5595,216.5812 C610.8338,216.5812 639.8529,216.5812 665.368,216.5812 " fill="none" id="S6<-S5" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="579.6714,216.5812,590.5084,221.3977,585.6919,216.5812,590.5084,211.7648,579.6714,216.5812" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="44.5521" x="599.3465" y="208.9003">continue</text><!--MD5=[5f6ea4567bb0950bff1d27387d49b4c2]
|
||||||
|
reverse link S7 to S6--><path d="M388.0009,216.5812 C413.0223,216.5812 440.9938,216.5812 464.8352,216.5812 " fill="none" id="S7<-S6" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="382.1489,216.5812,392.9996,221.3667,388.1694,216.564,392.9721,211.7339,382.1489,216.5812" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="40.9398" x="402.1733" y="208.9003">coalesce</text><!--MD5=[630b9631f886cf9c8b0d992525b86cf3]
|
||||||
|
reverse link S8 to S7--><path d="M132.1994,216.5812 C171.0802,216.5812 219.9551,216.5812 257.9689,216.5812 " fill="none" id="S8<-S7" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><polygon fill="#8095A1" points="126.3836,216.5812,137.2206,221.3977,132.4041,216.5812,137.2206,211.7648,126.3836,216.5812" style="stroke: #8095A1; stroke-width: 1.2041116005873715;"/><text fill="#000000" font-family="Monospace" font-size="10.837" lengthAdjust="spacingAndGlyphs" textLength="90.3084" x="145.9985" y="208.9003">oversized request</text><!--MD5=[2e2dc33d46c2ffc454d35cea5ea70934]
|
||||||
|
@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 — allocate, fragment, coalesce, verify
|
||||||
|
|
||||||
|
rectangle "01 RESET\ninitial free = 4080" as S1
|
||||||
|
rectangle "02 ALLOC A\n24 byte payload\nfirst-fit + split" as S2
|
||||||
|
rectangle "03 ALLOC B / C\n40 + 16 byte payload\nafter = 3952" as S3
|
||||||
|
rectangle "04 FREE A / C\nB remains allocated" as S4
|
||||||
|
rectangle "05 E01 FRAGMENTED\n2 free blocks\ncurrent > largest" as S5
|
||||||
|
rectangle "06 FREE B\ninsert by address\njoin right + left" as S6
|
||||||
|
rectangle "07 E02 COALESCED\n1 free block\nfinal = initial" as S7
|
||||||
|
rectangle "08 OOM CHECK\nNULL · hook=1\nasserts=0 · PASS=1" as S8
|
||||||
|
|
||||||
|
S1 -right-> S2 : pvPortMalloc
|
||||||
|
S2 -right-> S3 : split remainder
|
||||||
|
S3 -right-> S4 : vPortFree
|
||||||
|
S4 -down-> S5 : heap stats
|
||||||
|
S5 -left-> S6 : continue
|
||||||
|
S6 -left-> S7 : coalesce
|
||||||
|
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 |
@@ -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 — block state and heap statistics
|
||||||
|
|
||||||
|
[*] --> Free : 01 one list node
|
||||||
|
Free --> Allocated : 02 first-fit + split\ncurrent free decreases
|
||||||
|
Allocated --> Fragmented : free A and C
|
||||||
|
Fragmented : 03 two free blocks
|
||||||
|
Fragmented : sum free > largest block
|
||||||
|
Fragmented --> Coalesced : free B\naddress-order joins neighbours
|
||||||
|
Coalesced : 04 one free block
|
||||||
|
Coalesced : current free = initial free
|
||||||
|
Coalesced --> OOMChecked : request > arena
|
||||||
|
OOMChecked : NULL + hook once
|
||||||
|
OOMChecked --> [*]
|
||||||
|
|
||||||
|
state "05 minimum-ever" as MIN
|
||||||
|
Allocated -right-> MIN : records low watermark
|
||||||
|
Fragmented -right-> MIN : does not rise
|
||||||
|
Coalesced -right-> MIN : history remains
|
||||||
|
@enduml
|
||||||
@@ -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.2823px" preserveAspectRatio="none" style="width:346px;height:600px;" version="1.1" viewBox="0 0 346 600" width="346.9454px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="154.5281" x="99.1803" y="7.9418">A6 STATE — block state and heap statistics</text><ellipse cx="212.8476" cy="23.6993" fill="#000000" rx="7.4292" ry="7.4292" style="stroke: none; stroke-width: 0.742923663722561;"/><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="37.1462" x="194.2745" y="86.8478"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="194.2745" x2="231.4207" y1="104.3956" y2="104.3956"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="15.6014" x="205.0469" y="98.5042">Free</text><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="48.29" x="188.7026" y="190.1142"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="188.7026" x2="236.9926" y1="207.662" y2="207.662"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="33.4316" x="196.1318" y="201.7706">Allocated</text><rect fill="#EDF6FA" height="45.2143" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="101.0376" x="111.0671" y="282.9796"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="111.0671" x2="212.1047" y1="300.5275" y2="300.5275"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="43.0896" x="140.0411" y="294.6361">Fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="65.3773" x="114.7817" y="312.1839">03 two free blocks</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="86.1791" x="114.7817" y="322.3025">sum free > largest block</text><rect fill="#EDF6FA" height="45.2143" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="103.2664" x="4.4575" y="394.3142"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="4.4575" x2="107.7239" y1="411.862" y2="411.862"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="36.4033" x="37.8891" y="405.9706">Coalesced</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="61.6627" x="8.1722" y="423.5185">04 one free block</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="88.4079" x="8.1722" y="433.6371">current free = initial free</text><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="78.7499" x="16.7158" y="495.2478"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="16.7158" x2="95.4657" y1="512.7956" y2="512.7956"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="48.29" x="31.9457" y="506.9042">OOMChecked</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="63.8914" x="20.4304" y="524.4521">NULL + hook once</text><ellipse cx="56.0907" cy="585.1415" fill="none" rx="7.4292" ry="7.4292" style="stroke: #000000; stroke-width: 0.742923663722561;"/><ellipse cx="56.4622" cy="585.513" fill="#000000" rx="4.4575" ry="4.4575" style="stroke: none; stroke-width: 0.742923663722561;"/><rect fill="#EDF6FA" height="37.1462" rx="9.2865" ry="9.2865" style="stroke: #2C7794; stroke-width: 1.1143854955838415;" width="77.2641" x="190.5599" y="398.3482"/><line style="stroke: #2C7794; stroke-width: 1.1143854955838415;" x1="190.5599" x2="267.824" y1="415.8961" y2="415.8961"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="62.4056" x="197.9892" y="410.0047">05 minimum-ever</text><!--MD5=[f16808fa220dde377303612249059854]
|
||||||
|
link *start to Free--><path d="M212.8476,31.2845 C212.8476,42.3689 212.8476,64.7384 212.8476,81.885 " fill="none" id="*start->Free" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="212.8476,85.4436,215.8193,78.7573,212.8476,81.729,209.8759,78.7573,212.8476,85.4436" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="57.948" x="213.5906" y="62.101">01 one list node</text><!--MD5=[19abaf48dc778410378e95e0d1bca006]
|
||||||
|
link Free to Allocated--><path d="M212.8476,124.358 C212.8476,141.3635 212.8476,166.8235 212.8476,185.1663 " fill="none" id="Free->Allocated" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="212.8476,188.7843,215.8193,182.098,212.8476,185.0697,209.8759,182.098,212.8476,188.7843" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="59.4339" x="224.3629" y="154.9664">02 first-fit + split</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="80.9787" x="213.5906" y="165.085">current free decreases</text><!--MD5=[f6fa3e1917b73de38ea03346a6903b17]
|
||||||
|
link Allocated to Fragmented--><path d="M203.0856,227.6021 C195.3518,241.9925 184.4382,262.304 175.746,278.4849 " fill="none" id="Allocated->Fragmented" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="174.0076,281.7241,179.7784,277.2257,175.7573,278.4473,174.5357,274.4262,174.0076,281.7241" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="43.0896" x="191.028" y="258.2328">free A and C</text><!--MD5=[c73bca393b062d6a86dff80fa900c78c]
|
||||||
|
link Fragmented to Coalesced--><path d="M110.7031,318.744 C93.6455,325.4006 76.1571,335.4523 65.0058,350.4817 C56.8188,361.5141 54.33,376.536 54.0031,389.4331 " fill="none" id="Fragmented->Coalesced" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="53.9808,392.9546,56.9907,386.2854,54.0021,389.24,51.0474,386.2514,53.9808,392.9546" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="21.5448" x="110.6956" y="359.1664">free B</text><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="111.4385" x="65.7487" y="369.285">address-order joins neighbours</text><!--MD5=[2b306524d92469efb3bb270d490680cf]
|
||||||
|
link Coalesced to OOMChecked--><path d="M56.0907,439.7959 C56.0907,454.8922 56.0907,474.8471 56.0907,490.1216 " fill="none" id="Coalesced->OOMChecked" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="56.0907,493.7842,59.0624,487.0979,56.0907,490.0696,53.119,487.0979,56.0907,493.7842" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="57.2051" x="56.8337" y="470.501">request > arena</text><!--MD5=[6b8be85e17f6174335a5329fe1414850]
|
||||||
|
link OOMChecked to *end--><path d="M56.0907,532.55 C56.0907,545.306 56.0907,562.0366 56.0907,573.0022 " fill="none" id="OOMChecked->*end" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="56.0907,576.4716,59.0624,569.7853,56.0907,572.757,53.119,569.7853,56.0907,576.4716" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><!--MD5=[b09143a670c8c67aa163b99fca5c6b6b]
|
||||||
|
link Allocated to MIN--><path d="M228.8056,227.6169 C233.6049,234.1101 238.3299,241.7622 241.0787,249.548 C259.2432,300.9509 258.5449,318.5879 247.765,372.0264 C246.2941,379.3145 243.5824,386.8998 240.685,393.6827 " fill="none" id="Allocated->MIN" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="239.214,396.9813,244.6551,392.0892,240.7295,393.5899,239.2288,389.6643,239.214,396.9813" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="82.4645" x="256.1378" y="308.6996">records low watermark</text><!--MD5=[1fa23b8554d20d5dd3f2f8930c0e2df3]
|
||||||
|
link Fragmented to MIN--><path d="M172.2766,328.3871 C178.8143,341.366 187.6105,357.9332 196.5033,372.0264 C201.2283,379.5151 206.8225,387.3752 212.0378,394.3513 " fill="none" id="Fragmented->MIN" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="214.2072,397.2338,212.5727,390.1018,211.9784,394.2621,207.818,393.6678,214.2072,397.2338" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="46.8042" x="197.2462" y="364.3669">does not rise</text><!--MD5=[87522a40b34d64237ec6603d41372cd8]
|
||||||
|
link Coalesced to MIN--><path d="M108.0285,416.9213 C132.7679,416.9213 162.0242,416.9213 185.5972,416.9213 " fill="none" id="Coalesced->MIN" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><polygon fill="#8095A1" points="189.1038,416.9213,182.4175,413.9496,185.3892,416.9213,182.4175,419.893,189.1038,416.9213" style="stroke: #8095A1; stroke-width: 0.742923663722561;"/><text fill="#000000" font-family="Monospace" font-size="7.4292" lengthAdjust="spacingAndGlyphs" textLength="55.7193" x="121.2823" y="412.2335">history remains</text><!--MD5=[994b73c618d067de5faae1a7c19b4f86]
|
||||||
|
@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 — block state and heap statistics
|
||||||
|
|
||||||
|
[*] - -> Free : 01 one list node
|
||||||
|
Free - -> Allocated : 02 first-fit + split\ncurrent free decreases
|
||||||
|
Allocated - -> Fragmented : free A and C
|
||||||
|
Fragmented : 03 two free blocks
|
||||||
|
Fragmented : sum free > largest block
|
||||||
|
Fragmented - -> Coalesced : free B\naddress-order joins neighbours
|
||||||
|
Coalesced : 04 one free block
|
||||||
|
Coalesced : current free = initial free
|
||||||
|
Coalesced - -> OOMChecked : request > arena
|
||||||
|
OOMChecked : NULL + hook once
|
||||||
|
OOMChecked - -> [*]
|
||||||
|
|
||||||
|
state "05 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: 11 KiB |
@@ -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 — one artifact, two checkpoints, one proof
|
||||||
|
|
||||||
|
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
|
||||||
|
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
|
||||||
|
rectangle "<<checkpoint E01>>\n03 fragmented\nblocks=2 · aligned=1" as E1
|
||||||
|
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
|
||||||
|
rectangle "<<checkpoint E02>>\n05 coalesced\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
|
||||||
@@ -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="82.7447px" preserveAspectRatio="none" style="width:814px;height:82px;" version="1.1" viewBox="0 0 814 82" width="814.2079px" zoomAndPan="magnify"><defs/><g><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="190.3128" x="314.8436" y="7.9609">A7 RUNTIME — one artifact, two checkpoints, one proof</text><!--MD5=[183d75e42a7a852d02a7f9ce2cc3343f]
|
||||||
|
entity SRC--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="78.6075" x="4.9647" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="31.443" x="13.2392" y="38.0453">«source»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="38.89" x="13.2392" y="48.1882">01 task03 C</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="62.0585" x="13.2392" y="58.3311">A/B/C experiment</text><!--MD5=[4a7b087cd571ae358eb895b9dc7ce0ed]
|
||||||
|
entity ELF--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="71.9879" x="181.2109" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="32.2704" x="189.4854" y="38.0453">«artifact»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="51.3017" x="189.4854" y="48.1882">02 ELF + image</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="55.439" x="189.4854" y="58.3311">heap_4 symbols</text><!--MD5=[45565a74ca8123df0b8413ce5340d40a]
|
||||||
|
entity E1--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="86.0545" x="370.6963" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="60.4036" x="378.9707" y="38.0453">«checkpoint E01»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="52.1292" x="378.9707" y="48.1882">03 fragmented</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="69.5055" x="378.9707" y="58.3311">blocks=2 · aligned=1</text><!--MD5=[5ceda9279414f57783e95166b8d927b7]
|
||||||
|
entity MEM--><rect fill="#EDF6FA" height="46.9777" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="81.0898" x="553.5621" y="21.8099"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="37.2351" x="561.8365" y="38.0453">«memory»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="58.7487" x="561.8365" y="48.1882">04 ucHeap[4096]</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="64.5409" x="561.8365" y="58.3311">headers + payload</text><!--MD5=[a3c437a7ee715155cf6a0fec80d7cbaf]
|
||||||
|
entity E2--><rect fill="#EDF6FA" height="57.1206" style="stroke: #2C7794; stroke-width: 1.24117053481332;" width="88.5368" x="716.5691" y="16.7377"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="60.4036" x="724.8436" y="32.9731">«checkpoint E02»</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="43.0272" x="724.8436" y="43.116">05 coalesced</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="71.9879" x="724.8436" y="53.2589">final=initial · blocks=1</text><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="57.0938" x="724.8436" y="63.4018">OOM=1 · PASS=1</text><!--MD5=[2e73c4d4efa4a7715d66b06010e70f85]
|
||||||
|
link SRC to ELF--><path d="M83.961,45.2929 C111.3744,45.2929 148.0054,45.2929 175.7911,45.2929 " fill="none" id="SRC->ELF" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="179.6222,45.2929,172.1752,41.9831,175.485,45.2929,172.1752,48.6027,179.6222,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="46.337" x="109.223" y="42.497">compile + link</text><!--MD5=[98439561a91d683361f6e8599ebb304f]
|
||||||
|
link ELF to E1--><path d="M253.5463,45.2929 C284.8735,45.2929 330.7719,45.2929 365.2765,45.2929 " fill="none" id="ELF->E1" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="369.2482,45.2929,361.8012,41.9831,365.111,45.2929,361.8012,48.6027,369.2482,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="66.1958" x="278.8496" y="42.497">reset / load / replay</text><!--MD5=[14b84038a04448f34eb55bd119f2d935]
|
||||||
|
link E1 to MEM--><path d="M457.1314,45.2929 C484.5447,45.2929 520.1332,45.2929 548.0513,45.2929 " fill="none" id="E1->MEM" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="551.9154,45.2929,544.4684,41.9831,547.7782,45.2929,544.4684,48.6027,551.9154,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="45.5096" x="482.4016" y="42.497">inspect bytes</text><!--MD5=[28f0a5a321106494a7afb95cbc1e35b0]
|
||||||
|
link MEM to E2--><path d="M634.8918,45.2929 C657.8783,45.2929 686.93,45.2929 711.2486,45.2929 " fill="none" id="MEM->E2" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><polygon fill="#8095A1" points="715.1128,45.2929,707.6658,41.9831,710.9756,45.2929,707.6658,48.6027,715.1128,45.2929" style="stroke: #8095A1; stroke-width: 0.82744702320888;"/><text fill="#000000" font-family="Monospace" font-size="7.447" lengthAdjust="spacingAndGlyphs" textLength="30.6155" x="660.3027" y="42.497">continue</text><!--MD5=[bc1681809f0cb7bb82cdf81f0385b8f2]
|
||||||
|
@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 — one artifact, two checkpoints, one proof
|
||||||
|
|
||||||
|
rectangle "<<source>>\n01 task03 C\nA/B/C experiment" as SRC
|
||||||
|
rectangle "<<artifact>>\n02 ELF + image\nheap_4 symbols" as ELF
|
||||||
|
rectangle "<<checkpoint E01>>\n03 fragmented\nblocks=2 · aligned=1" as E1
|
||||||
|
rectangle "<<memory>>\n04 ucHeap[4096]\nheaders + payload" as MEM
|
||||||
|
rectangle "<<checkpoint E02>>\n05 coalesced\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.4 KiB |
@@ -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>
|
||||||