1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36 package ti.sysbios.knl;
37
38 import xdc.rov.ViewInfo;
39
40 /*!
41 * ======== Queue ========
42 * Queue manager.
43 *
44 * The Queue module makes available a set of functions that manipulate
45 * queue objects accessed through handles of type Queue_Handle.
46 * Each queue contains a linked sequence of zero or more elements
47 * referenced through variables of type Queue_Elem, which are
48 * embedded as the first field within a structure.
49 *
50 * In the Queue API descriptions, the APIs which disable interrupts before
51 * modifying the Queue are noted as "atomic", while APIs that do not disable
52 * interrupts are "non-atomic".
53 *
54 * Queues are represented as doubly-linked lists, so calls to Queue_next
55 * or Queue_prev can loop continuously over the Queue. The following code
56 * demonstrates one way to iterate over a Queue once from beginning to end.
57 * In this example, 'myQ' is a Queue_Handle.
58 *
59 * @p(code)
60 * Queue_Elem *elem;
61 *
62 * for (elem = Queue_head(myQ);
63 * elem != (Queue_Elem *)myQ;
64 * elem = Queue_next(elem)) {
65 * ...
66 * }
67 * @p
68 *
69 * Below is a simple example of how to create a Queue, enqueue two elements,
70 * and dequeue the elements until the queue is empty:
71 *
72 * @p(code)
73 * #include <xdc/std.h>
74 * #include <xdc/runtime/System.h>
75 *
76 * #include <ti/sysbios/knl/Queue.h>
77 *
78 * typedef struct Rec {
79 * Queue_Elem _elem;
80 * Int data;
81 * } Rec;
82 *
83 * Int main(Int argc, Char *argv[])
84 * {
85 * Queue_Handle q;
86 * Rec r1, r2;
87 * Rec* rp;
88 *
89 * r1.data = 100;
90 * r2.data = 200;
91 *
92 *
93 * // create a Queue instance 'q'
94 * q = Queue_create(NULL, NULL);
95 *
96 *
97 * // enQ a couple of records
98 * Queue_enqueue(q, &r1._elem);
99 * Queue_enqueue(q, &r2._elem);
100 *
101 *
102 * // deQ the records and print their data values until Q is empty
103 * while (!Queue_empty(q)) {
104 * rp = Queue_dequeue(q);
105 * System_printf("rec: %d\n", rp->data);
106 * }
107 *
108 * System_exit(0);
109 * return (0);
110 * }
111 * @p
112 *
113 *
114 *
115 * Unconstrained Functions
116 * All functions are unconstrained
117 *
118 * @p(html)
119 * <h3> Calling Context </h3>
120 * <table border="1" cellpadding="3">
121 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
122 * </colgroup>
123 *
124 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
125 * <th> Task </th><th> Main </th><th> Startup </th></tr>
126 * <!-- -->
127 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
128 * <td> Y </td><td> Y </td><td> N </td></tr>
129 * <tr><td> {@link #insert} </td><td> Y </td><td> Y </td>
130 * <td> Y </td><td> Y </td><td> N </td></tr>
131 * <tr><td> {@link #next} </td><td> Y </td><td> Y </td>
132 * <td> Y </td><td> Y </td><td> N </td></tr>
133 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
134 * <td> Y </td><td> Y </td><td> N </td></tr>
135 * <tr><td> {@link #prev} </td><td> Y </td><td> Y </td>
136 * <td> Y </td><td> Y </td><td> N </td></tr>
137 * <tr><td> {@link #remove} </td><td> Y </td><td> Y </td>
138 * <td> Y </td><td> Y </td><td> N </td></tr>
139 * <tr><td> {@link #construct} </td><td> Y </td><td> Y </td>
140 * <td> Y </td><td> Y </td><td> N </td></tr>
141 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
142 * <td> Y </td><td> Y </td><td> N </td></tr>
143 * <tr><td> {@link #dequeue} </td><td> Y </td><td> Y </td>
144 * <td> Y </td><td> Y </td><td> N </td></tr>
145 * <tr><td> {@link #destruct} </td><td> Y </td><td> Y </td>
146 * <td> Y </td><td> Y </td><td> N </td></tr>
147 * <tr><td> {@link #empty} </td><td> Y </td><td> Y </td>
148 * <td> Y </td><td> Y </td><td> N </td></tr>
149 * <tr><td> {@link #enqueue} </td><td> Y </td><td> Y </td>
150 * <td> Y </td><td> Y </td><td> N </td></tr>
151 * <tr><td> {@link #get} </td><td> Y </td><td> Y </td>
152 * <td> Y </td><td> Y </td><td> N </td></tr>
153 * <tr><td> {@link #head} </td><td> Y </td><td> Y </td>
154 * <td> Y </td><td> Y </td><td> N </td></tr>
155 * <tr><td> {@link #put} </td><td> Y </td><td> Y </td>
156 * <td> Y </td><td> Y </td><td> N </td></tr>
157 * <tr><td colspan="6"> Definitions: <br />
158 * <ul>
159 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
160 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
161 * <li> <b>Task</b>: API is callable from a Task thread. </li>
162 * <li> <b>Main</b>: API is callable during any of these phases: </li>
163 * <ul>
164 * <li> In your module startup after this module is started
165 * (e.g. Queue_Module_startupDone() returns TRUE). </li>
166 * <li> During xdc.runtime.Startup.lastFxns. </li>
167 * <li> During main().</li>
168 * <li> During BIOS.startupFxns.</li>
169 * </ul>
170 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
171 * <ul>
172 * <li> During xdc.runtime.Startup.firstFxns.</li>
173 * <li> In your module startup before this module is started
174 * (e.g. Queue_Module_startupDone() returns FALSE).</li>
175 * </ul>
176 * </ul>
177 * </td></tr>
178 *
179 * </table>
180 * @p
181 */
182
183 @DirectCall
184
185 @InstanceInitStatic
186 module Queue
187 {
188
189 /*!
190 * ======== BasicView ========
191 * @_nodoc
192 */
193 metaonly struct BasicView {
194 String label;
195 Ptr elems[];
196 }
197
198 /*!
199 * ======== rovViewInfo ========
200 * @_nodoc
201 */
202 @Facet
203 metaonly config ViewInfo.Instance rovViewInfo =
204 ViewInfo.create({
205 viewMap: [
206 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}]
207 ]
208 });
209
210 /*!
211 * ======== Elem ========
212 * Opaque queue element.
213 *
214 * A field of this type is placed at the head of client structs.
215 */
216
217 struct Elem {
218 Elem *volatile next;
219 Elem *volatile prev;
220 };
221
222 /*!
223 * @_nodoc
224 * ======== elemClear ========
225 * Clears a Queue element's pointers so that if isQueued() is called on
226 * the element it will return FALSE. When a Queue element is dequeued or
227 * removed from a Queue, this API must be called on the element for
228 * isQueued() to return FALSE.
229 *
230 * To be clear, this API is not for removing elements from a queue, and
231 * should never be called on an element in a queue--only on dequeued
232 * elements.
233 *
234 * @param(qelem) element to be cleared
235 */
236 Void elemClear(Elem *qelem);
237
238 /*!
239 * ======== elemClearMeta ========
240 * @_nodoc
241 * Clears a Queue element's pointers so that if isQueued() is called on
242 * the element it will return FALSE. When a Queue element is dequeued or
243 * removed from a Queue, this API must be called on the element for
244 * isQueued() to return FALSE.
245 *
246 * To be clear, this API is not for removing elements from a queue, and
247 * should never be called on an element in a queue--only on dequeued
248 * elements.
249 *
250 * @param(qelem) element to be cleared
251 */
252 metaonly Void elemClearMeta(Elem *qelem);
253
254 /*!
255 * ======== insert ========
256 * Insert `elem` in the queue in front of `qelem`.
257 *
258 * @param(qelem) element already in queue
259 *
260 * @param(elem) element to be inserted in queue
261 */
262
263 Void insert(Elem *qelem, Elem *elem);
264
265 /*!
266 * ======== insertMeta ========
267 * @_nodoc
268 * Insert `elem` in the queue in front of `qelem`.
269 *
270 * @param(qelem) element already in queue
271 *
272 * @param(elem) element to be inserted in queue
273 */
274 metaonly Void insertMeta(Elem *qelem, Elem *elem);
275
276 /*!
277 * ======== next ========
278 * Return next element in queue (non-atomically).
279 *
280 * This function returns a pointer to an Elem object in the queue
281 * after `qelem`. A Queue is represented internally as a doubly-linked
282 * list, so 'next' can be called in a continuous loop over the queue.
283 * See the module description for an example of iterating once over a
284 * Queue.
285 *
286 * @param(qelem) element in queue
287 *
288 * @b(returns) next element in queue
289 */
290
291 Ptr next(Elem *qelem);
292
293 /*!
294 * ======== prev ========
295 * Return previous element in queue (non-atomically).
296 *
297 * This function returns a pointer to an Elem object in the queue
298 * before `qelem`. A Queue is represented internally as a doubly-linked
299 * list, so 'prev' can be called in a continuous loop over the queue.
300 * See the module description for an example of iterating once over a
301 * Queue.
302 *
303 * @param(qelem) element in queue
304 *
305 * @b(returns) previous element in queue
306 */
307
308 Ptr prev(Elem *qelem);
309
310 /*!
311 * ======== remove ========
312 * Remove qelem from middle of queue (non-atomically).
313 *
314 * The `qelem` parameter is a pointer to an existing element to be removed
315 * from the Queue.
316 *
317 * @param(qelem) element in queue
318 */
319 Void remove (Elem *qelem);
320
321 /*!
322 * @_nodoc
323 * ======== isQueued ========
324 * Check if the elem is on any queue.
325 *
326 * In order for this API to return false on an element that has been
327 * dequeued or removed from a Queue, elemClear must have been called on
328 * the element.
329 *
330 * @param(qelem) element in queue
331 */
332 Bool isQueued (Elem *qelem);
333
334 instance:
335
336
337 /*!
338 * @_nodoc
339 * Added to get the Grace instance view to work.
340 */
341 metaonly config UInt dummy = 0;
342
343 /*!
344 * ======== create ========
345 * Create a Queue object
346 */
347 create();
348
349 /*!
350 * ======== dequeue ========
351 * Remove the element from the front of queue and return elem
352 * (non-atomically).
353 *
354 * This function removes an element from the front of a queue and returns
355 * it.
356 *
357 * If called with an empty queue, this function will return a pointer to
358 * the queue itself.
359 *
360 * @a(note) As this function is non-atomic, the method for detecting an
361 * empty Queue as shown in {@link #get Queue_get()} isn't reliable in
362 * a multi-threaded system. Thread safety can be achieved as shown below:
363 *
364 * @p(code)
365 * key = Hwi_disable();
366 *
367 * if ((Queue_Handle)(elem = Queue_dequeue(q)) != q) {
368 * ` process elem `
369 * }
370 *
371 * Hwi_restore(key);
372 * @p
373 *
374 * @b(returns) pointer to former first element
375 */
376
377 Ptr dequeue();
378
379 /*!
380 * ======== empty ========
381 * Test for an empty queue.
382 *
383 * @b(returns) TRUE if this queue is empty
384 */
385
386 Bool empty();
387
388 /*!
389 * ======== enqueue ========
390 * Insert at end of queue (non-atomically).
391 *
392 * @param(elem) pointer to an element
393 */
394
395 Void enqueue(Elem *elem);
396
397 /*!
398 * ======== get ========
399 * Get element from front of queue (atomically).
400 *
401 * This function removes an element from the front of a queue and returns
402 * it.
403 *
404 * If called with an empty queue, this function will return a pointer to
405 * the queue itself.
406 * This provides a means for using a single atomic action to check if a
407 * queue is empty, and to remove and return the first element if it is
408 * not empty:
409 *
410 * @p(code)
411 * if ((Queue_Handle)(elem = Queue_get(q)) != q) {
412 * ` process elem `
413 * }
414 * @p
415 *
416 * @b(returns) pointer to former first element
417 */
418
419 Ptr get();
420
421 /*!
422 * ======== getTail ========
423 * Get the element at the end of the queue (atomically).
424 *
425 * This function removes the element at the end of a queue and returns
426 * a pointer to it.
427 * If called with an empty queue, this function will return a pointer to
428 * the queue itself.
429 * This provides a means for using a single atomic action to check if a
430 * queue is empty, and to remove and return the last element if it is
431 * not empty:
432 *
433 * @p(code)
434 * if ((Queue_Handle)(elem = Queue_getTail(q)) != q) {
435 * `process elem`
436 * }
437 * @p
438 *
439 * @b(returns) pointer to former end element
440 */
441
442 Ptr getTail();
443
444 /*!
445 * ======== head ========
446 * Return element at front of queue. (atomically)
447 *
448 * This function returns a pointer to the element at the front of a queue.
449 * The element is not removed from the queue.
450 * If called with an empty queue, this function will return a pointer to
451 * the queue itself.
452 * This provides a means for using a single atomic action to check if a queue
453 * is empty, and to return a pointer to the first element if it is not empty:
454 *
455 * @p(code)
456 * if ((Queue_Handle)(elem = Queue_head(q)) != q) {
457 * `process elem`
458 * @p
459 *
460 * @b(returns) pointer to first element
461 */
462 Ptr head();
463
464 /*!
465 * ======== headMeta ========
466 * @_nodoc
467 * Return element at front of queue. Returns null if queue is empty.
468 *
469 * This function returns a pointer to the element at the front of queue.
470 * The element is not removed from the queue.
471 *
472 * @b(returns) pointer to first element
473 */
474 metaonly Ptr headMeta();
475
476 /*!
477 * ======== put ========
478 * Put element at end of queue (atomically).
479 *
480 * @param(elem) pointer to new queue element
481 */
482
483 Void put(Elem *elem);
484
485 /*!
486 * ======== putMeta ========
487 * @_nodoc
488 * Put element at end of queue.
489 *
490 * @param(elem) pointer to new queue element
491 */
492 metaonly Void putMeta(Elem* elem);
493
494 /*!
495 * ======== putHead ========
496 * Put element at the front of the queue (atomically).
497 *
498 * @param(elem) pointer to new queue element
499 */
500
501 Void putHead(Elem *elem);
502
503 /*!
504 * ======== nextMeta ========
505 * @_nodoc
506 * Return next element in queue. Returns null if end of queue.
507 *
508 * This function returns a pointer to an Elem object in the queue
509 * after `qelem`.
510 *
511 * @param(qelem) element in queue
512 *
513 * @b(returns) next element in queue
514 */
515 metaonly Ptr nextMeta(Elem *qelem);
516
517 internal:
518
519
520 struct Instance_State {
521 Elem elem;
522 };
523 }