Loading...
Searching...
No Matches
queue.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _PICO_UTIL_QUEUE_H
8#define _PICO_UTIL_QUEUE_H
9
10#include "pico.h"
11#include "hardware/sync.h"
12
13// PICO_CONFIG: PICO_QUEUE_MAX_LEVEL, Maintain a field for the highest level that has been reached by a queue, type=bool, default=0, advanced=true, group=queue
14#ifndef PICO_QUEUE_MAX_LEVEL
15#define PICO_QUEUE_MAX_LEVEL 0
16#endif
17
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30#include "pico/lock_core.h"
31
39typedef struct {
40 lock_core_t core;
41 uint8_t *data;
42 uint16_t wptr;
43 uint16_t rptr;
44 uint16_t element_size;
45 uint16_t element_count;
46#if PICO_QUEUE_MAX_LEVEL
47 uint16_t max_level;
48#endif
49} queue_t;
50
60bool queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num);
61
70static inline bool queue_init(queue_t *q, uint element_size, uint element_count) {
71 return queue_init_with_spinlock(q, element_size, element_count, next_striped_spin_lock_num());
72}
73
81void queue_free(queue_t *q);
82
92static inline uint queue_get_level_unsafe(queue_t *q) {
93 int32_t rc = (int32_t)q->wptr - (int32_t)q->rptr;
94 if (rc < 0) {
95 rc += q->element_count + 1;
96 }
97 return (uint)rc;
98}
99
106static inline uint queue_get_level(queue_t *q) {
107 uint32_t save = spin_lock_blocking(q->core.spin_lock);
108 uint level = queue_get_level_unsafe(q);
109 spin_unlock(q->core.spin_lock, save);
110 return level;
111}
112
113#if PICO_QUEUE_MAX_LEVEL
121static inline uint queue_get_max_level(queue_t *q) {
122 return q->max_level;
123}
124#endif
125
126#if PICO_QUEUE_MAX_LEVEL
132static inline void queue_reset_max_level(queue_t *q) {
133 uint32_t save = spin_lock_blocking(q->core.spin_lock);
134 q->max_level = queue_get_level_unsafe(q);
135 spin_unlock(q->core.spin_lock, save);
136}
137#endif
138
147static inline bool queue_is_empty(queue_t *q) {
148 return queue_get_level(q) == 0;
149}
150
159static inline bool queue_is_full(queue_t *q) {
160 return queue_get_level(q) == q->element_count;
161}
162
163// nonblocking queue access functions:
164
175bool queue_try_add(queue_t *q, const void *data);
176
187bool queue_try_remove(queue_t *q, void *data);
188
199bool queue_try_peek(queue_t *q, void *data);
200
201// blocking queue access functions:
202
213void queue_add_blocking(queue_t *q, const void *data);
214
225void queue_remove_blocking(queue_t *q, void *data);
226
237void queue_peek_blocking(queue_t *q, void *data);
238
239#ifdef __cplusplus
240}
241#endif
242#endif
static __force_inline uint32_t spin_lock_blocking(spin_lock_t *lock)
Acquire a spin lock safely.
Definition spin_lock.h:354
static __force_inline void spin_unlock(spin_lock_t *lock, uint32_t saved_irq)
Release a spin lock safely.
Definition spin_lock.h:385
uint next_striped_spin_lock_num(void)
Return a spin lock number from the striped range.
Definition sync.c:18
void queue_peek_blocking(queue_t *q, void *data)
Blocking peek at next value to be removed from queue.
Definition queue.c:125
static uint queue_get_level_unsafe(queue_t *q)
Unsafe check of level of the specified queue.
Definition queue.h:92
bool queue_try_remove(queue_t *q, void *data)
Non-blocking removal of entry from the queue if non empty.
Definition queue.c:109
bool queue_try_add(queue_t *q, const void *data)
Non-blocking add value queue if not full.
Definition queue.c:105
static uint queue_get_level(queue_t *q)
Check of level of the specified queue.
Definition queue.h:106
static bool queue_is_empty(queue_t *q)
Check if queue is empty.
Definition queue.h:147
void queue_remove_blocking(queue_t *q, void *data)
Blocking remove entry from queue.
Definition queue.c:121
void queue_free(queue_t *q)
Destroy the specified queue.
Definition queue.c:21
bool queue_try_peek(queue_t *q, void *data)
Non-blocking peek at the next item to be removed from the queue.
Definition queue.c:113
void queue_add_blocking(queue_t *q, const void *data)
Blocking add of value to queue.
Definition queue.c:117
bool queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num)
Initialise a queue with a specific spinlock for concurrency protection.
Definition queue.c:11
static bool queue_init(queue_t *q, uint element_size, uint element_count)
Initialise a queue, allocating a (possibly shared) spinlock.
Definition queue.h:70
static bool queue_is_full(queue_t *q)
Check if queue is full.
Definition queue.h:159
spin_lock_t * spin_lock
Spin lock protecting this lock's state.
Definition lock_core.h:70
A multi-core and IRQ safe queue instance.
Definition queue.h:39
lock_core_t core
Core lock state used for synchronisation.
Definition queue.h:40
uint16_t element_count
Maximum number of elements the queue can hold.
Definition queue.h:45
uint8_t * data
Pointer to the backing data buffer.
Definition queue.h:41
uint16_t rptr
Read pointer (index of next slot to read).
Definition queue.h:43
uint16_t element_size
Size in bytes of each element.
Definition queue.h:44
uint16_t wptr
Write pointer (index of next slot to write).
Definition queue.h:42