---
title: "Heaps"
canonical_url: https://developer.repebble.com/pebbleos/docs/samples/kernel/heap/
last_updated: 2026-11-13
sdk_version: 4.44
---
# Heaps

Source: https://developer.repebble.com/pebbleos/docs/samples/kernel/heap/

This sample gives a 2 KiB buffer a heap of its own, with a mutex as its lock, and watches its usage: full, then with every other block freed, where plenty of memory is free but no block of twice the size fits, then empty again.

Sizes include a header per block, and differ between a watch and the native build. For memory that needs no bound of its own, `pbl_malloc()` allocates from the kernel heap.

Run:

`pbl samples samples/kernel/heap`

Boards:

every board

## Sources

src/main.c

```
#include \<errno.h\>#include \<stdint.h\>#include \<pbl/kernel/compiler.h\>#include \<pbl/kernel/heap.h\>#include \<pbl/kernel/mutex.h\>#include \<pbl/logging/logging.h\>#include \<pbl/util/size.h\>#define CALLER ((uintptr\_t)PBL\_RETURN\_ADDRESS(0))#define BLOCK\_SIZE 100U/\* A heap of its own bounds what one user can take, here a 2 KiB cache. \*/static uint8\_t s\_region[2048];static struct pbl\_heap s\_heap;static PBL\_MUTEX\_DEFINE(s\_heap\_mutex);static void prv\_lock(void \*ctx) {pbl\_mutex\_lock(ctx, PBL\_FOREVER);}static void prv\_unlock(void \*ctx) {pbl\_mutex\_unlock(ctx);}static void prv\_log\_usage(const char \*when) {unsigned int used;unsigned int free;unsigned int max\_free;pbl\_heap\_stats(&s\_heap, &used, &free, &max\_free);PBL\_LOG\_INFO("heap: %s: %u used, %u free, largest free block %u", when, used, free, max\_free);}int main(void) {void \*blocks[32];size\_t num\_blocks = 0;char \*name;void \*big;pbl\_heap\_init(&s\_heap, s\_region, s\_region + sizeof(s\_region), false);/\* Heaps do not lock on their own: one used from several threads is given a lock. \*/pbl\_heap\_set\_lock(&s\_heap, (struct pbl\_heap\_lock){.lock = prv\_lock,.unlock = prv\_unlock,.ctx = &s\_heap\_mutex,});prv\_log\_usage("empty");name = pbl\_heap\_strdup(&s\_heap, "a string on the heap", CALLER);if (name == NULL) {PBL\_LOG\_ERR("heap: out of memory");return -ENOMEM;}PBL\_LOG\_INFO("heap: block is in the heap: %s, allocated: %s",pbl\_heap\_contains(&s\_heap, name) ? "yes" : "no",pbl\_heap\_is\_allocated(&s\_heap, name) ? "yes" : "no");pbl\_heap\_free(&s\_heap, name, CALLER);/\* Allocation fails with NULL, which the caller handles. \*/while (num\_blocks \< ARRAY\_LENGTH(blocks)) {blocks[num\_blocks] = pbl\_heap\_alloc(&s\_heap, BLOCK\_SIZE, CALLER);if (blocks[num\_blocks] == NULL) {break;}num\_blocks++;}PBL\_LOG\_INFO("heap: full after %u blocks of %u bytes", (unsigned int)num\_blocks, BLOCK\_SIZE);prv\_log\_usage("full");/\* Every other block freed: plenty of memory in total, but in pieces. \*/for (size\_t i = 0; i \< num\_blocks; i += 2) {pbl\_heap\_free(&s\_heap, blocks[i], CALLER);}prv\_log\_usage("every other block freed");big = pbl\_heap\_alloc(&s\_heap, 2 \* BLOCK\_SIZE, CALLER);PBL\_LOG\_INFO("heap: %u bytes from a fragmented heap: %s", 2 \* BLOCK\_SIZE,big == NULL ? "refused" : "allocated");/\* Freed neighbors merge, so the pieces become one block again. \*/for (size\_t i = 1; i \< num\_blocks; i += 2) {pbl\_heap\_free(&s\_heap, blocks[i], CALLER);}prv\_log\_usage("all freed");PBL\_LOG\_INFO("heap: least memory it ever had left: %u of %u bytes",(unsigned int)pbl\_heap\_min\_headroom(&s\_heap), (unsigned int)pbl\_heap\_size(&s\_heap));PBL\_LOG\_INFO("Sample done");return 0;}
```

## Output

```
heap: empty: 0 used, \d+ free, largest free block \d+
heap: block is in the heap: yes, allocated: yes
heap: full after \d+ blocks of 100 bytes
heap: full: \d+ used, \d+ free, largest free block \d+
heap: every other block freed: \d+ used, \d+ free, largest free block \d+
heap: 200 bytes from a fragmented heap: refused
heap: all freed: 0 used, \d+ free, largest free block \d+
heap: least memory it ever had left: \d+ of \d+ bytes
Sample done
```

Generated from PebbleOS [f4926c952](https://github.com/coredevices/pebbleos/commit/f4926c952bf9b82bce9e3cdb44645a59531c0ee9). This page is maintained in the pebbleos repository: [docs/samples/kernel/heap.md](https://github.com/coredevices/pebbleos/blob/f4926c952bf9b82bce9e3cdb44645a59531c0ee9/docs/samples/kernel/heap.md).
