Mistake on this page?
Report an issue in GitHub or email us
equeue.h
1 
2 /*
3  * Flexible event queue for dispatching events
4  *
5  * Copyright (c) 2016-2019 ARM Limited
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 #ifndef EQUEUE_H
21 #define EQUEUE_H
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 // Platform specific files
28 #include "events/internal/equeue_platform.h"
29 
30 #include <stddef.h>
31 #include <stdint.h>
32 
33 /**
34  * \addtogroup events-public-api
35  * @{
36  */
37 
38 // The minimum size of an event
39 // This size is guaranteed to fit events created by event_call
40 #define EQUEUE_EVENT_SIZE (sizeof(struct equeue_event) + 2*sizeof(void*))
41 
42 // Internal event structure
43 struct equeue_event {
44  unsigned size;
45  uint16_t generation;
46  uint8_t id;
47 
48  struct equeue_event *next;
49  struct equeue_event *sibling;
50  struct equeue_event **ref;
51 
52  unsigned target;
53  int period;
54  void (*dtor)(void *);
55 
56  void (*cb)(void *);
57  // data follows
58 };
59 
60 // Event queue structure
61 typedef struct equeue {
62  struct equeue_event *queue;
63  unsigned tick;
64 
65  uint16_t generation;
66  bool break_requested;
67 
68  unsigned char *buffer;
69  unsigned npw2;
70  void *allocated;
71 
72  struct equeue_event *chunks;
73  struct equeue_slab {
74  size_t size;
75  unsigned char *data;
76  } slab;
77 
79  bool active;
80  void (*update)(void *timer, int ms);
81  void *timer;
82  } background;
83 
84  equeue_sema_t eventsema;
85  equeue_mutex_t queuelock;
86  equeue_mutex_t memlock;
87 } equeue_t;
88 
89 
90 // Queue lifetime operations
91 //
92 // Creates and destroys an event queue. The event queue either allocates a
93 // buffer of the specified size with malloc or uses a user provided buffer
94 // if constructed with equeue_create_inplace.
95 //
96 // If the event queue creation fails, equeue_create returns a negative,
97 // platform-specific error code.
98 //
99 // If queues are chained, it is needed to unchain them first, before calling destroy,
100 // or call the destroy function on queues in order that chained queues are destroyed first.
101 int equeue_create(equeue_t *queue, size_t size);
102 int equeue_create_inplace(equeue_t *queue, size_t size, void *buffer);
103 void equeue_destroy(equeue_t *queue);
104 
105 // Dispatch events
106 //
107 // Executes events until the specified milliseconds have passed. If ms is
108 // negative, equeue_dispatch will dispatch events indefinitely or until
109 // equeue_break is called on this queue.
110 //
111 // When called with a finite timeout, the equeue_dispatch function is
112 // guaranteed to terminate. When called with a timeout of 0, the
113 // equeue_dispatch does not wait and is irq safe.
114 void equeue_dispatch(equeue_t *queue, int ms);
115 
116 // Break out of a running event loop
117 //
118 // Forces the specified event queue's dispatch loop to terminate. Pending
119 // events may finish executing, but no new events will be executed.
120 void equeue_break(equeue_t *queue);
121 
122 // Simple event calls
123 //
124 // The specified callback will be executed in the context of the event queue's
125 // dispatch loop. When the callback is executed depends on the call function.
126 //
127 // equeue_call - Immediately post an event to the queue
128 // equeue_call_in - Post an event after a specified time in milliseconds
129 // equeue_call_every - Post an event periodically every milliseconds
130 //
131 // All equeue_call functions are irq safe and can act as a mechanism for
132 // moving events out of irq contexts.
133 //
134 // The return value is a unique id that represents the posted event and can
135 // be passed to equeue_cancel. If there is not enough memory to allocate the
136 // event, equeue_call returns an id of 0.
137 int equeue_call(equeue_t *queue, void (*cb)(void *), void *data);
138 int equeue_call_in(equeue_t *queue, int ms, void (*cb)(void *), void *data);
139 int equeue_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data);
140 
141 // Allocate memory for events
142 //
143 // The equeue_alloc function allocates an event that can be manually dispatched
144 // with equeue_post. The equeue_dealloc function may be used to free an event
145 // that has not been posted. Once posted, an event's memory is managed by the
146 // event queue and should not be deallocated.
147 //
148 // Both equeue_alloc and equeue_dealloc are irq safe.
149 //
150 // The equeue allocator is designed to minimize jitter in interrupt contexts as
151 // well as avoid memory fragmentation on small devices. The allocator achieves
152 // both constant-runtime and zero-fragmentation for fixed-size events, however
153 // grows linearly as the quantity of different sized allocations increases.
154 //
155 // The equeue_alloc function returns a pointer to the event's allocated memory
156 // and acts as a handle to the underlying event. If there is not enough memory
157 // to allocate the event, equeue_alloc returns null.
158 void *equeue_alloc(equeue_t *queue, size_t size);
159 void equeue_dealloc(equeue_t *queue, void *event);
160 
161 // Configure an allocated event
162 //
163 // equeue_event_delay - Millisecond delay before dispatching an event
164 // equeue_event_period - Millisecond period for repeating dispatching an event
165 // equeue_event_dtor - Destructor to run when the event is deallocated
166 void equeue_event_delay(void *event, int ms);
167 void equeue_event_period(void *event, int ms);
168 void equeue_event_dtor(void *event, void (*dtor)(void *));
169 
170 // Post an event onto the event queue
171 //
172 // The equeue_post function takes a callback and a pointer to an event
173 // allocated by equeue_alloc. The specified callback will be executed in the
174 // context of the event queue's dispatch loop with the allocated event
175 // as its argument.
176 //
177 // The equeue_post function is irq safe and can act as a mechanism for
178 // moving events out of irq contexts.
179 //
180 // The return value is a unique id that represents the posted event and can
181 // be passed to equeue_cancel.
182 int equeue_post(equeue_t *queue, void (*cb)(void *), void *event);
183 
184 // Post an user allocated event onto the event queue
185 //
186 // The equeue_post_user_allocated function takes a callback and a pointer
187 // to an event allocated by user. The specified callback will be executed
188 // in the context of the event queue's dispatch loop with the allocated
189 // event as its argument.
190 //
191 // The equeue_post_user_allocated function is irq safe and can act as
192 // a mechanism for moving events out of irq contexts.
193 void equeue_post_user_allocated(equeue_t *queue, void (*cb)(void *), void *event);
194 
195 // Cancel an in-flight event
196 //
197 // Attempts to cancel an event referenced by the unique id returned from
198 // equeue_call or equeue_post. It is not safe to call equeue_cancel after an event
199 // has already been dispatched.
200 //
201 // The equeue_cancel function is irq safe.
202 //
203 // If called while the event queue's dispatch loop is active in another thread,
204 // equeue_cancel does not guarantee that the event will not execute after it returns as
205 // the event may have already begun executing.
206 // Returning true guarantees that cancel succeeded and event will not execute.
207 // Returning false if invalid id or already started executing.
208 bool equeue_cancel(equeue_t *queue, int id);
209 
210 // Cancel an in-flight user allocated event
211 //
212 // Attempts to cancel an event referenced by its address.
213 // It is not safe to call equeue_cancel_user_allocated after an event
214 // has already been dispatched.
215 //
216 // The equeue_cancel_user_allocated function is irq safe.
217 //
218 // If called while the event queue's dispatch loop is active,
219 // equeue_cancel_user_allocated does not guarantee that the event
220 // will not execute after it returns as the event may have
221 // already begun executing.
222 bool equeue_cancel_user_allocated(equeue_t *queue, void *event);
223 
224 // Query how much time is left for delayed event
225 //
226 // If event is delayed, this function can be used to query how much time
227 // is left until the event is due to be dispatched.
228 //
229 // This function is irq safe.
230 //
231 int equeue_timeleft(equeue_t *q, int id);
232 
233 // Query how much time is left for delayed user allocated event
234 //
235 // If event is delayed, this function can be used to query how much time
236 // is left until the event is due to be dispatched.
237 //
238 // This function is irq safe.
239 //
240 int equeue_timeleft_user_allocated(equeue_t *q, void *event);
241 
242 // Background an event queue onto a single-shot timer
243 //
244 // The provided update function will be called to indicate when the queue
245 // should be dispatched. A negative timeout will be passed to the update
246 // function when the timer is no longer needed.
247 //
248 // Passing a null update function disables the existing timer.
249 //
250 // The equeue_background function allows an event queue to take advantage
251 // of hardware timers or even other event loops, allowing an event queue to
252 // be effectively backgrounded.
253 void equeue_background(equeue_t *queue,
254  void (*update)(void *timer, int ms), void *timer);
255 
256 // Chain an event queue onto another event queue
257 //
258 // After chaining a queue to a target, calling equeue_dispatch on the
259 // target queue will also dispatch events from this queue. The queues
260 // use their own buffers and events must be managed independently.
261 //
262 // Passing a null queue as the target will unchain the existing queue.
263 //
264 // The equeue_chain function allows multiple equeues to be composed, sharing
265 // the context of a dispatch loop while still being managed independently.
266 //
267 // If the event queue chaining fails, equeue_chain returns a negative,
268 // platform-specific error code.
269 int equeue_chain(equeue_t *queue, equeue_t *target);
270 
271 /** @}*/
272 
273 #ifdef __cplusplus
274 }
275 #endif
276 
277 #endif
Definition: equeue.h:61
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.