---
title: "Priority inversion"
canonical_url: https://developer.repebble.com/pebbleos/docs/samples/kernel/classic/priority_inversion/
last_updated: 2026-11-13
sdk_version: 4.44
---
# Priority inversion

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

This sample has a low priority thread hold a mutex that `main()`, of high priority, needs, while a medium priority thread that needs no lock keeps the CPU busy. The mutex lends the high priority to its holder, so the wait lasts as long as the low thread’s work, not the medium one’s.

Without inheritance, medium would run before low, and high would wait for a thread it has nothing to do with. Semaphores do not inherit, as they have no owner: another reason to guard data with mutexes.

Run:

`pbl samples samples/kernel/classic/priority_inversion`

Boards:

every board but native\_emery, native\_flint, native\_gabbro

## Sources

src/main.c

```
#include \<inttypes.h\>#include \<pbl/kernel/delay.h\>#include \<pbl/kernel/mutex.h\>#include \<pbl/kernel/thread.h\>#include \<pbl/kernel/time.h\>#include \<pbl/logging/logging.h\>/\* main() is the high priority thread. \*/#define MEDIUM\_PRIO (CONFIG\_KERNEL\_MAIN\_THREAD\_PRIO - 1)#define LOW\_PRIO (CONFIG\_KERNEL\_MAIN\_THREAD\_PRIO - 2)static PBL\_MUTEX\_DEFINE(s\_bus\_lock);static volatile bool s\_high\_waits;static volatile bool s\_medium\_done;PBL\_THREAD\_STACK\_DEFINE(s\_low\_stack, 1024);PBL\_THREAD\_STACK\_DEFINE(s\_medium\_stack, 1024);static const struct pbl\_thread \*s\_high;static struct pbl\_thread s\_low;static struct pbl\_thread s\_medium;static void prv\_use\_cpu(uint32\_t ms) {uint64\_t start = pbl\_uptime\_ms();while (pbl\_uptime\_ms() - start \< ms) {}}static void prv\_low(void \*arg) {const struct pbl\_thread \*self = pbl\_thread\_current();pbl\_mutex\_lock(&s\_bus\_lock, PBL\_FOREVER);/\* A long piece of work, which high comes in the middle of. \*/while (!s\_high\_waits) {}prv\_use\_cpu(10);/\* While high waits for the lock, its holder runs at high's priority. \*/PBL\_LOG\_INFO("low: ends its work at the priority of high: %s",self-\>prio == s\_high-\>prio ? "yes" : "no");pbl\_mutex\_unlock(&s\_bus\_lock);PBL\_LOG\_INFO("low: back to its own priority: %s",self-\>prio == pbl\_thread\_prio\_get(self) ? "yes" : "no");}/\* Needs no lock, only the CPU, and for longer than high can wait. \*/static void prv\_medium(void \*arg) {prv\_use\_cpu(100);s\_medium\_done = true;PBL\_LOG\_INFO("medium: done");}static void prv\_start(struct pbl\_thread \*t, const char \*name, pbl\_thread\_entry\_t entry,pbl\_prio\_t prio, void \*stack, size\_t stack\_size) {const struct pbl\_thread\_attr attr = {.name = name,.entry = entry,.prio = prio,.privileged = true,.stack = stack,.stack\_size = stack\_size,};pbl\_thread\_create(t, &attr);}int main(void) {int ret;s\_high = pbl\_thread\_current();prv\_start(&s\_low, "low", prv\_low, LOW\_PRIO, s\_low\_stack, sizeof(s\_low\_stack));/\* Lets low take the lock. \*/pbl\_sleep\_ms(5);/\* Ready to run, and above low: without inheritance it would run first, for 100 ms. \*/prv\_start(&s\_medium, "medium", prv\_medium, MEDIUM\_PRIO, s\_medium\_stack, sizeof(s\_medium\_stack));s\_high\_waits = true;ret = pbl\_mutex\_lock(&s\_bus\_lock, PBL\_FOREVER);if (ret != 0) {PBL\_LOG\_ERR("high: cannot take the lock (%d)", ret);return ret;}PBL\_LOG\_INFO("high: got the lock %s medium had the CPU", s\_medium\_done ? "after" : "before");pbl\_mutex\_unlock(&s\_bus\_lock);ret = PBL\_POLL\_SLEEP\_MS(pbl\_thread\_state(&s\_low) == PBL\_THREAD\_DEAD, 5, 1000);if (ret != 0) {PBL\_LOG\_ERR("high: low did not end (%d)", ret);return ret;}PBL\_LOG\_INFO("Sample done");return 0;}
```

## Output

```
low: ends its work at the priority of high: yes
high: got the lock before medium had the CPU
medium: done
low: back to its own priority: yes
Sample done
```

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