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

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

This sample passes samples from a producer thread to `main()` through a queue of two messages. The producer blocks when the queue is full, so the consumer sets the pace. It then shows what a full queue answers to a caller that does not wait, and how an urgent message gets ahead of the others.

The consumer stops on the first `pbl_msgq_get()` that times out. Messages are copied, so the producer builds each one on its stack. [Bounded buffer](https://developer.repebble.com/pebbleos/docs/samples/kernel/classic/bounded_buffer.md) builds the same thing from semaphores.

Run:

`pbl samples samples/kernel/msgq`

Boards:

every board

## Sources

src/main.c

```
#include \<errno.h\>#include \<inttypes.h\>#include \<pbl/kernel/msgq.h\>#include \<pbl/kernel/thread.h\>#include \<pbl/logging/logging.h\>#define QUEUE\_LEN 2#define NUM\_SAMPLES 5struct sample {uint32\_t seq;int32\_t value;};/\* Messages are copied in and out, so the queue owns all the storage it needs. \*/static PBL\_MSGQ\_DEFINE(s\_samples, sizeof(struct sample), QUEUE\_LEN);PBL\_THREAD\_STACK\_DEFINE(s\_producer\_stack, 1024);static struct pbl\_thread s\_producer;static void prv\_producer(void \*arg) {for (uint32\_t seq = 0; seq \< NUM\_SAMPLES; seq++) {const struct sample sample = {.seq = seq, .value = (int32\_t)seq \* 10};/\* Blocks while the queue is full: a slow consumer slows the producer down. \*/int ret = pbl\_msgq\_put(&s\_samples, &sample, PBL\_FOREVER);if (ret != 0) {PBL\_LOG\_ERR("producer: put failed (%d)", ret);return;}}}static int prv\_consume(void) {uint32\_t received = 0;struct sample sample;int ret;for (;;) {ret = pbl\_msgq\_get(&s\_samples, &sample, PBL\_MSEC(100));if (ret == -EAGAIN) {break;} else if (ret != 0) {return ret;}PBL\_LOG\_INFO("consumer: sample %" PRIu32 " = %" PRId32, sample.seq, sample.value);received++;}PBL\_LOG\_INFO("consumer: no sample for 100 ms, %" PRIu32 " received", received);return received == NUM\_SAMPLES ? 0 : -EIO;}static int prv\_jump\_the\_queue(void) {const struct sample routine = {.seq = 100};const struct sample urgent = {.seq = 999};struct sample sample;int ret;ret = pbl\_msgq\_put(&s\_samples, &routine, PBL\_NO\_WAIT);if (ret != 0) {return ret;}ret = pbl\_msgq\_put\_front(&s\_samples, &urgent, PBL\_NO\_WAIT);if (ret != 0) {return ret;}/\* The queue is full: without waiting, a third message is refused. \*/ret = pbl\_msgq\_put(&s\_samples, &routine, PBL\_NO\_WAIT);PBL\_LOG\_INFO("main: put on a full queue returns %s", ret == -EBUSY ? "-EBUSY" : "something else");ret = pbl\_msgq\_get(&s\_samples, &sample, PBL\_NO\_WAIT);if (ret != 0) {return ret;}PBL\_LOG\_INFO("main: sample %" PRIu32 " was put last and comes out first", sample.seq);pbl\_msgq\_purge(&s\_samples);return 0;}int main(void) {const struct pbl\_thread\_attr attr = {.name = "producer",.entry = prv\_producer,.prio = CONFIG\_KERNEL\_MAIN\_THREAD\_PRIO - 1,.privileged = true,.stack = s\_producer\_stack,.stack\_size = sizeof(s\_producer\_stack),};struct sample sample;int ret;pbl\_thread\_create(&s\_producer, &attr);/\* Let the producer run until the queue stops it. \*/pbl\_thread\_sleep(PBL\_MSEC(50));PBL\_LOG\_INFO("main: producer is blocked with %" PRIu32 " of %u samples queued",pbl\_msgq\_num\_used(&s\_samples), NUM\_SAMPLES);ret = pbl\_msgq\_peek(&s\_samples, &sample);if (ret != 0) {PBL\_LOG\_ERR("main: peek failed (%d)", ret);return ret;}PBL\_LOG\_INFO("main: sample %" PRIu32 " is next, and still queued", sample.seq);ret = prv\_consume();if (ret != 0) {PBL\_LOG\_ERR("main: consuming failed (%d)", ret);return ret;}ret = prv\_jump\_the\_queue();if (ret != 0) {PBL\_LOG\_ERR("main: jumping the queue failed (%d)", ret);return ret;}PBL\_LOG\_INFO("Sample done");return 0;}
```

## Output

```
main: producer is blocked with 2 of 5 samples queued
main: sample 0 is next, and still queued
consumer: sample 0 = 0
consumer: sample 1 = 10
consumer: sample 2 = 20
consumer: sample 3 = 30
consumer: sample 4 = 40
consumer: no sample for 100 ms, 5 received
main: put on a full queue returns -EBUSY
main: sample 999 was put last and comes out first
Sample done
```

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