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