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 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 #include "pico/lock_core.h"
31 
32 typedef struct {
33  lock_core_t core;
34  uint8_t *data;
35  uint16_t wptr;
36  uint16_t rptr;
37  uint16_t element_size;
38  uint16_t element_count;
39 #if PICO_QUEUE_MAX_LEVEL
40  uint16_t max_level;
41 #endif
42 } queue_t;
43 
52 void queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num);
53 
61 static inline void queue_init(queue_t *q, uint element_size, uint element_count) {
62  queue_init_with_spinlock(q, element_size, element_count, next_striped_spin_lock_num());
63 }
64 
72 void queue_free(queue_t *q);
73 
83 static inline uint queue_get_level_unsafe(queue_t *q) {
84  int32_t rc = (int32_t)q->wptr - (int32_t)q->rptr;
85  if (rc < 0) {
86  rc += q->element_count + 1;
87  }
88  return (uint)rc;
89 }
90 
97 static inline uint queue_get_level(queue_t *q) {
98  uint32_t save = spin_lock_blocking(q->core.spin_lock);
99  uint level = queue_get_level_unsafe(q);
100  spin_unlock(q->core.spin_lock, save);
101  return level;
102 }
103 
104 #if PICO_QUEUE_MAX_LEVEL
112 static inline uint queue_get_max_level(queue_t *q) {
113  return q->max_level;
114 }
115 #endif
116 
117 #if PICO_QUEUE_MAX_LEVEL
123 static inline void queue_reset_max_level(queue_t *q) {
124  uint32_t save = spin_lock_blocking(q->core.spin_lock);
125  q->max_level = queue_get_level_unsafe(q);
126  spin_unlock(q->core.spin_lock, save);
127 }
128 #endif
129 
138 static inline bool queue_is_empty(queue_t *q) {
139  return queue_get_level(q) == 0;
140 }
141 
150 static inline bool queue_is_full(queue_t *q) {
151  return queue_get_level(q) == q->element_count;
152 }
153 
154 // nonblocking queue access functions:
155 
166 bool queue_try_add(queue_t *q, const void *data);
167 
178 bool queue_try_remove(queue_t *q, void *data);
179 
190 bool queue_try_peek(queue_t *q, void *data);
191 
192 // blocking queue access functions:
193 
202 void queue_add_blocking(queue_t *q, const void *data);
203 
212 void queue_remove_blocking(queue_t *q, void *data);
213 
222 void queue_peek_blocking(queue_t *q, void *data);
223 
224 #ifdef __cplusplus
225 }
226 #endif
227 #endif
static __force_inline uint32_t spin_lock_blocking(spin_lock_t *lock)
Acquire a spin lock safely.
Definition: sync.h:287
static __force_inline void spin_unlock(spin_lock_t *lock, uint32_t saved_irq)
Release a spin lock safely.
Definition: sync.h:314
uint next_striped_spin_lock_num(void)
Return a spin lock number from the striped range.
Definition: sync.c:31
static void queue_init(queue_t *q, uint element_size, uint element_count)
Initialise a queue, allocating a (possibly shared) spinlock.
Definition: queue.h:61
void queue_peek_blocking(queue_t *q, void *data)
Blocking peek at next value to be removed from queue.
Definition: queue.c:117
static uint queue_get_level_unsafe(queue_t *q)
Unsafe check of level of the specified queue.
Definition: queue.h:83
bool queue_try_remove(queue_t *q, void *data)
Non-blocking removal of entry from the queue if non empty.
Definition: queue.c:101
bool queue_try_add(queue_t *q, const void *data)
Non-blocking add value queue if not full.
Definition: queue.c:97
static uint queue_get_level(queue_t *q)
Check of level of the specified queue.
Definition: queue.h:97
void 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_is_empty(queue_t *q)
Check if queue is empty.
Definition: queue.h:138
void queue_remove_blocking(queue_t *q, void *data)
Blocking remove entry from queue.
Definition: queue.c:113
void queue_free(queue_t *q)
Destroy the specified queue.
Definition: queue.c:20
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:105
void queue_add_blocking(queue_t *q, const void *data)
Blocking add of value to queue.
Definition: queue.c:109
static bool queue_is_full(queue_t *q)
Check if queue is full.
Definition: queue.h:150
Definition: lock_core.h:53
Definition: queue.h:32