Skip to content

Add sentinel for free lists to eliminate NULL-check#16

Merged
jserv merged 1 commit intomasterfrom
sentinel
Feb 8, 2026
Merged

Add sentinel for free lists to eliminate NULL-check#16
jserv merged 1 commit intomasterfrom
sentinel

Conversation

@jserv
Copy link
Copy Markdown
Collaborator

@jserv jserv commented Feb 8, 2026

This embeds a block_null sentinel in tlsf_t so all empty free-list bin pointers point to the sentinel instead of NULL, removing three data-dependent branches on the hot path: two in remove_free_block (prev/next NULL checks) and one in insert_free_block (current NULL check), replacing them with unconditional writes that are harmless when they hit the sentinel.

Both initialization paths are covered: tlsf_pool_init sets all bin pointers to &block_null after memset, and arena_grow does so lazily on first use of a dynamic pool (before any free-list operation).


Summary by cubic

Embed a free-list sentinel (block_null) in tlsf_t so empty bins point to it, removing NULL checks in the hot path. This drops three data-dependent branches and replaces them with safe unconditional writes.

  • Refactors
    • Add block_null sentinel in tlsf_t; empty free-list heads point to it.
    • Remove NULL guards in insert_free_block and remove_free_block; detect empty via sentinel.
    • Initialize bins to sentinel in tlsf_pool_init and on first arena_grow; update tlsf_check to treat sentinel as empty.

Written for commit 207b645. Summary will update on new commits.

This embeds a block_null sentinel in tlsf_t so all empty free-list bin
pointers point to the sentinel instead of NULL, removing three
data-dependent branches on the hot path: two in remove_free_block
(prev/next NULL checks) and one in insert_free_block (current NULL
check), replacing them with unconditional writes that are harmless when
they hit the sentinel.

Both initialization paths are covered: tlsf_pool_init sets all bin
pointers to &block_null after memset, and arena_grow does so lazily
on first use of a dynamic pool (before any free-list operation).
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 8, 2026

WCET Results (x86-64)

TLSF WCET Analysis
==================
Timer:      cycles
Cache:      hot
Pool:       4194304 bytes (4.0 MB)
Iterations: 5000 (warmup: 500)
Sizes:      16 64 256 1024 4096 bytes

--- malloc_worst (small alloc from single huge block) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         73         98         98         98        172        196       89.4       12.3
      64         73         98         98        123        196        270       94.0       14.2
     256         73         98         98         98        171        221       90.3       11.8
    1024         73         98         98         98        147      26239       96.4      370.0
    4096         73         98         98         98        147        196       94.2        9.4

--- malloc_best (exact bin hit, no split) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         49         74         98         98        122        172       77.2       10.5
      64         49         74         74         98         98        147       74.4        8.7
     256         49         74         74         98         98        147       74.1        8.5
    1024         49         73         74         98         98        147       71.8        8.1
    4096         49         74         74         98         98        147       75.9        7.7

--- free_worst (sandwiched between two free blocks) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         49         74         98         98         98        221       75.8        9.7
      64         49         74         98         98        147        270       77.3       10.5
     256         49         74         98         98        147        221       75.4       10.7
    1024         49         74         98         98        147        220       75.1       10.2
    4096         49         74         98         98        147        196       76.3       11.1

--- free_best (no merge (used neighbors)) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         49         49         74         74        123        196       61.4       12.9
      64         49         49         74         74        196        220       58.8       13.0
     256         49         73         74         74        123        220       62.6       12.9
    1024         49         73         74         74        123        196       63.0       12.7
    4096         49         73         74         74        196        220       62.2       13.5

--- worst/best ratio (p99) ---
    size     malloc       free
      16      1.00x      1.32x
      64      1.00x      1.32x
     256      1.00x      1.32x
    1024      1.00x      1.32x
    4096      1.00x      1.32x

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 8, 2026

WCET Results (arm64)

TLSF WCET Analysis
==================
Timer:      ticks
Cache:      hot
Pool:       4194304 bytes (4.0 MB)
Iterations: 5000 (warmup: 500)
Sizes:      16 64 256 1024 4096 bytes

--- malloc_worst (small alloc from single huge block) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         16         32         32         32         40         48       30.9        2.9
      64         16         32         32         32         40       4144       32.3       71.9
     256         16         32         32         32         40         40       30.8        3.0
    1024         24         32         32         32         40       6696       32.1       94.3
    4096         24         32         32         40         40         40       31.1        2.8

--- malloc_best (exact bin hit, no split) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16          8         24         32         32         32       1776       25.8       24.9
      64         16         24         32         32         32         32       25.4        3.1
     256         16         24         32         32         32         32       25.4        3.0
    1024         16         24         32         32         32         32       25.4        3.1
    4096         24         24         32         32         32         40       25.4        3.1

--- free_worst (sandwiched between two free blocks) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         16         24         32         32         32         40       25.8        3.3
      64         16         24         32         32         32         48       25.9        3.4
     256          8         24         32         32         32         40       25.8        3.4
    1024         16         24         32         32         32         40       25.9        3.5
    4096         24         24         32         32         32         40       26.2        3.6

--- free_best (no merge (used neighbors)) ---
    size        min        p50        p90        p99      p99.9        max       mean     stddev
      16         16         24         24         24         24         32       20.6        4.0
      64         16         24         24         24         24         32       20.5        4.0
     256         16         24         24         24         24         24       20.5        4.0
    1024          8         24         24         24         24         32       20.7        4.0
    4096          8         24         24         24         24         32       20.6        4.0

--- worst/best ratio (p99) ---
    size     malloc       free
      16      1.00x      1.33x
      64      1.00x      1.33x
     256      1.00x      1.33x
    1024      1.00x      1.33x
    4096      1.00x      1.33x

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@jserv jserv merged commit 6141e9b into master Feb 8, 2026
10 checks passed
@jserv jserv deleted the sentinel branch February 8, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant