source: rtems/cpukit/sapi/include/rtems/chain.h @ b1564cc

4.11
Last change on this file since b1564cc was b1564cc, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 22, 2013 at 2:27:30 PM

sapi: Merge chain implementation into one file

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief Chain API
5 */
6
7/*
8 *  Copyright (c) 2010 embedded brains GmbH.
9 *
10 *  COPYRIGHT (c) 1989-2008.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.com/license/LICENSE.
16 */
17
18#ifndef _RTEMS_CHAIN_H
19#define _RTEMS_CHAIN_H
20
21#include <rtems/score/chainimpl.h>
22#include <rtems/rtems/event.h>
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/**
29 * @defgroup ClassicChains Chains
30 *
31 * @ingroup ClassicRTEMS
32 *
33 * @brief Chain API
34 */
35/**@{**/
36
37typedef Chain_Node rtems_chain_node;
38
39typedef Chain_Control rtems_chain_control;
40
41/**
42 *  @brief Chain initializer for an empty chain with designator @a name.
43 */
44#define RTEMS_CHAIN_INITIALIZER_EMPTY(name) \
45  CHAIN_INITIALIZER_EMPTY(name)
46
47/**
48 *  @brief Chain definition for an empty chain with designator @a name.
49 */
50#define RTEMS_CHAIN_DEFINE_EMPTY(name) \
51  CHAIN_DEFINE_EMPTY(name)
52
53/**
54 * @brief Appends the @a node to the @a chain and sends the @a events to the
55 * @a task if the @a chain was empty before the append.
56 *
57 * @see rtems_chain_append_with_empty_check() and rtems_event_send().
58 *
59 * @retval RTEMS_SUCCESSFUL Successful operation.
60 * @retval RTEMS_INVALID_ID No such task.
61 */
62rtems_status_code rtems_chain_append_with_notification(
63  rtems_chain_control *chain,
64  rtems_chain_node *node,
65  rtems_id task,
66  rtems_event_set events
67);
68
69/**
70 * @brief Prepends the @a node to the @a chain and sends the @a events to the
71 * @a task if the @a chain was empty before the prepend.
72 *
73 * @see rtems_chain_prepend_with_empty_check() and rtems_event_send().
74 *
75 * @retval RTEMS_SUCCESSFUL Successful operation.
76 * @retval RTEMS_INVALID_ID No such task.
77 */
78rtems_status_code rtems_chain_prepend_with_notification(
79  rtems_chain_control *chain,
80  rtems_chain_node *node,
81  rtems_id task,
82  rtems_event_set events
83);
84
85/**
86 * @brief Gets the first @a node of the @a chain and sends the @a events to the
87 * @a task if the @a chain is empty after the get.
88 *
89 * @see rtems_chain_get_with_empty_check() and rtems_event_send().
90 *
91 * @retval RTEMS_SUCCESSFUL Successful operation.
92 * @retval RTEMS_INVALID_ID No such task.
93 */
94rtems_status_code rtems_chain_get_with_notification(
95  rtems_chain_control *chain,
96  rtems_id task,
97  rtems_event_set events,
98  rtems_chain_node **node
99);
100
101/**
102 * @brief Gets the first @a node of the @a chain and sends the @a events to the
103 * @a task if the @a chain is empty afterwards.
104 *
105 * @see rtems_chain_get() and rtems_event_receive().
106 *
107 * @retval RTEMS_SUCCESSFUL Successful operation.
108 * @retval RTEMS_TIMEOUT Timeout.
109 */
110rtems_status_code rtems_chain_get_with_wait(
111  rtems_chain_control *chain,
112  rtems_event_set events,
113  rtems_interval timeout,
114  rtems_chain_node **node
115);
116
117/**
118 * @brief Initialize a chain Header.
119 *
120 * This routine initializes @a the_chain structure to manage the
121 * contiguous array of @a number_nodes nodes which starts at
122 * @a starting_address.  Each node is of @a node_size bytes.
123 *
124 * @param[in] the_chain specifies the chain to initialize
125 * @param[in] starting_address is the starting address of the array
126 *        of elements
127 * @param[in] number_nodes is the number of nodes that will be in the chain
128 * @param[in] node_size is the size of each node
129 */
130RTEMS_INLINE_ROUTINE void rtems_chain_initialize(
131  rtems_chain_control *the_chain,
132  void                *starting_address,
133  size_t               number_nodes,
134  size_t               node_size
135)
136{
137  _Chain_Initialize( the_chain, starting_address, number_nodes, node_size );
138}
139
140/**
141 * @brief Initialize this chain as empty.
142 *
143 * This routine initializes the specified chain to contain zero nodes.
144 *
145 * @param[in] the_chain is the chain to be initialized.
146 */
147RTEMS_INLINE_ROUTINE void rtems_chain_initialize_empty(
148  rtems_chain_control *the_chain
149)
150{
151  _Chain_Initialize_empty( the_chain );
152}
153
154/**
155 * @brief Set off chain.
156 *
157 * This function sets the next and previous fields of the @a node to NULL
158 * indicating the @a node is not part of a chain.
159 *
160 * @param[in] node the node set to off chain.
161 */
162RTEMS_INLINE_ROUTINE void rtems_chain_set_off_chain(
163  rtems_chain_node *node
164)
165{
166  _Chain_Set_off_chain( node );
167}
168
169/**
170 * @brief Is the node off chain.
171 *
172 * This function returns true if the @a node is not on a chain. A @a node is
173 * off chain if the next and previous fields are set to NULL.
174 *
175 * @param[in] node is the node off chain.
176 *
177 * @retval true The node is off chain.
178 * @retval false The node is not off chain.
179 */
180RTEMS_INLINE_ROUTINE bool rtems_chain_is_node_off_chain(
181  const rtems_chain_node *node
182)
183{
184  return _Chain_Is_node_off_chain( node );
185}
186
187/**
188 * @brief Is the chain node pointer NULL.
189 *
190 * This function returns true if the_node is NULL and false otherwise.
191 *
192 * @param[in] the_node is the node pointer to check.
193 *
194 * @retval true The chain node pointer is NULL.
195 * @retval false The chain node pointer is not NULL.
196 */
197RTEMS_INLINE_ROUTINE bool rtems_chain_is_null_node(
198  const rtems_chain_node *the_node
199)
200{
201  return _Chain_Is_null_node( the_node );
202}
203
204/**
205 * @brief Return pointer to Chain Head
206 *
207 * This function returns a pointer to the first node on the chain.
208 *
209 * @param[in] the_chain is the chain to be operated upon.
210 *
211 * @return This method returns the permanent node of the chain.
212 */
213RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_head(
214  rtems_chain_control *the_chain
215)
216{
217  return _Chain_Head( the_chain );
218}
219
220/**
221 * @brief Return pointer to immutable Chain Head
222 *
223 * This function returns a pointer to the head node on the chain.
224 *
225 * @param[in] the_chain is the chain to be operated upon.
226 *
227 * @return This method returns the permanent head node of the chain.
228 */
229RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_head(
230  const rtems_chain_control *the_chain
231)
232{
233  return _Chain_Immutable_head( the_chain );
234}
235
236/**
237 * @brief Return pointer to Chain Tail
238 *
239 * This function returns a pointer to the tail node on the chain.
240 *
241 * @param[in] the_chain is the chain to be operated upon.
242 *
243 * @return This method returns the permanent tail node of the chain.
244 */
245RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_tail(
246  rtems_chain_control *the_chain
247)
248{
249  return _Chain_Tail( the_chain );
250}
251
252/**
253 * @brief Return pointer to immutable Chain Tail
254 *
255 * This function returns a pointer to the tail node on the chain.
256 *
257 * @param[in] the_chain is the chain to be operated upon.
258 *
259 * @return This method returns the permanent tail node of the chain.
260 */
261RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_tail(
262  const rtems_chain_control *the_chain
263)
264{
265  return _Chain_Immutable_tail( the_chain );
266}
267
268/**
269 * @brief Return pointer to Chain's First node after the permanent head.
270 *
271 * This function returns a pointer to the first node on the chain after the
272 * head.
273 *
274 * @param[in] the_chain is the chain to be operated upon.
275 *
276 * @return This method returns the first node of the chain.
277 */
278RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_first(
279  rtems_chain_control *the_chain
280)
281{
282  return _Chain_First( the_chain );
283}
284
285/**
286 * @brief Return pointer to immutable Chain's First node
287 *
288 * This function returns a pointer to the first node on the chain after the
289 * head.
290 *
291 * @param[in] the_chain is the chain to be operated upon.
292 *
293 * @return This method returns the first node of the chain.
294 */
295RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_first(
296  const rtems_chain_control *the_chain
297)
298{
299  return _Chain_Immutable_first( the_chain );
300}
301
302/**
303 * @brief Return pointer to Chain's Last node before the permanent tail.
304 *
305 * This function returns a pointer to the last node on the chain just before
306 * the tail.
307 *
308 * @param[in] the_chain is the chain to be operated upon.
309 *
310 * @return This method returns the last node of the chain.
311 */
312RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_last(
313  rtems_chain_control *the_chain
314)
315{
316  return _Chain_Last( the_chain );
317}
318
319/**
320 * @brief Return pointer to immutable Chain's Last node
321 *
322 * This function returns a pointer to the last node on the chain just before
323 * the tail.
324 *
325 * @param[in] the_chain is the chain to be operated upon.
326 *
327 * @return This method returns the last node of the chain.
328 */
329RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_last(
330  const rtems_chain_control *the_chain
331)
332{
333  return _Chain_Immutable_last( the_chain );
334}
335
336/**
337 * @brief Return pointer the next node from this node
338 *
339 * This function returns a pointer to the next node after this node.
340 *
341 * @param[in] the_node is the node to be operated upon.
342 *
343 * @return This method returns the next node on the chain.
344 */
345RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_next(
346  rtems_chain_node *the_node
347)
348{
349  return _Chain_Next( the_node );
350}
351
352/**
353 * @brief Return pointer the immutable next node from this node
354 *
355 * This function returns a pointer to the next node after this node.
356 *
357 * @param[in] the_node is the node to be operated upon.
358 *
359 * @return This method returns the next node on the chain.
360 */
361RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_next(
362  const rtems_chain_node *the_node
363)
364{
365  return _Chain_Immutable_next( the_node );
366}
367
368/**
369 * @brief Return pointer the previous node from this node
370 *
371 * This function returns a pointer to the previous node on this chain.
372 *
373 * @param[in] the_node is the node to be operated upon.
374 *
375 * @return This method returns the previous node on the chain.
376 */
377RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_previous(
378  rtems_chain_node *the_node
379)
380{
381  return _Chain_Previous( the_node );
382}
383
384/**
385 * @brief Return pointer the immutable previous node from this node.
386 *
387 * This function returns a pointer to the previous node on this chain.
388 *
389 * @param[in] the_node is the node to be operated upon.
390 *
391 * @return This method returns the previous node on the chain.
392 */
393RTEMS_INLINE_ROUTINE const rtems_chain_node *rtems_chain_immutable_previous(
394  const rtems_chain_node *the_node
395)
396{
397  return _Chain_Immutable_previous( the_node );
398}
399
400/**
401 * @brief Are Two nodes equal.
402 *
403 * This function returns true if @a left and @a right are equal,
404 * and false otherwise.
405 *
406 * @param[in] left is the node on the left hand side of the comparison.
407 * @param[in] right is the node on the left hand side of the comparison.
408 *
409 * @retval true @a left is equal to @a right.
410 * @retval false @a left is not equal to @a right
411 */
412RTEMS_INLINE_ROUTINE bool rtems_chain_are_nodes_equal(
413  const rtems_chain_node *left,
414  const rtems_chain_node *right
415)
416{
417  return _Chain_Are_nodes_equal( left, right );
418}
419
420/**
421 * @brief Is the chain empty
422 *
423 * This function returns true if there a no nodes on @a the_chain and
424 * false otherwise.
425 *
426 * @param[in] the_chain is the chain to be operated upon.
427 *
428 * @retval true The chain is empty.
429 * @retval false The chain is not empty.
430 */
431RTEMS_INLINE_ROUTINE bool rtems_chain_is_empty(
432  const rtems_chain_control *the_chain
433)
434{
435  return _Chain_Is_empty( the_chain );
436}
437
438/**
439 * @brief Is this the first node on the chain.
440 *
441 * This function returns true if the_node is the first node on a chain and
442 * false otherwise.
443 *
444 * @param[in] the_node is the node the caller wants to know if it is
445 *            the first node on a chain.
446 *
447 * @retval true @a the_node is the first node on a chain.
448 * @retval false @a the_node is not the first node on a chain.
449 */
450RTEMS_INLINE_ROUTINE bool rtems_chain_is_first(
451  const rtems_chain_node *the_node
452)
453{
454  return _Chain_Is_first( the_node );
455}
456
457/**
458 * @brief Is this the last node on the chain.
459 *
460 * This function returns true if @a the_node is the last node on a chain and
461 * false otherwise.
462 *
463 * @param[in] the_node is the node to check as the last node.
464 *
465 * @retval true @a the_node is the last node on a chain.
466 * @retval false @a the_node is not the last node on a chain
467 */
468RTEMS_INLINE_ROUTINE bool rtems_chain_is_last(
469  const rtems_chain_node *the_node
470)
471{
472  return _Chain_Is_last( the_node );
473}
474
475/**
476 * @brief Does this chain have only one node.
477 *
478 * This function returns true if there is only one node on @a the_chain and
479 * false otherwise.
480 *
481 * @param[in] the_chain is the chain to be operated upon.
482 *
483 * @retval true The chain has only one node.
484 * @retval false The chain has more than one nodes.
485 */
486RTEMS_INLINE_ROUTINE bool rtems_chain_has_only_one_node(
487  const rtems_chain_control *the_chain
488)
489{
490  return _Chain_Has_only_one_node( the_chain );
491}
492
493/**
494 * @brief Is this node the chain head.
495 *
496 * This function returns true if @a the_node is the head of the_chain and
497 * false otherwise.
498 *
499 * @param[in] the_chain is the chain to be operated upon.
500 * @param[in] the_node is the node to check for being the Chain Head.
501 *
502 * @retval true @a the_node is the head of @a the_chain.
503 * @retval false @a the_node is not the head of @a the_chain.
504 */
505RTEMS_INLINE_ROUTINE bool rtems_chain_is_head(
506  const rtems_chain_control *the_chain,
507  const rtems_chain_node *the_node
508)
509{
510  return _Chain_Is_head( the_chain, the_node );
511}
512
513/**
514 * @brief Is this node the chain tail.
515 *
516 * This function returns true if the_node is the tail of the_chain and
517 * false otherwise.
518 *
519 * @param[in] the_chain is the chain to be operated upon.
520 * @param[in] the_node is the node to check for being the Chain Tail.
521 *
522 * @retval true @a the_node is the tail of @a the_chain.
523 * @retval false @a the_node is not the tail of @a the_chain.
524 */
525RTEMS_INLINE_ROUTINE bool rtems_chain_is_tail(
526  const rtems_chain_control *the_chain,
527  const rtems_chain_node *the_node
528)
529{
530  return _Chain_Is_tail( the_chain, the_node );
531}
532
533/**
534 * @brief Extract the specified node from a chain.
535 *
536 * This routine extracts @a the_node from the chain on which it resides.
537 * It disables interrupts to ensure the atomicity of the
538 * extract operation.
539 *
540 * @arg the_node specifies the node to extract
541 */
542RTEMS_INLINE_ROUTINE void rtems_chain_extract(
543  rtems_chain_node *the_node
544)
545{
546  _Chain_Extract( the_node );
547}
548
549/**
550 * @brief Extract the specified node from a chain (unprotected).
551 *
552 * This routine extracts @a the_node from the chain on which it resides.
553 *
554 * NOTE: It does NOT disable interrupts to ensure the atomicity of the
555 * append operation.
556 */
557RTEMS_INLINE_ROUTINE void rtems_chain_extract_unprotected(
558  rtems_chain_node *the_node
559)
560{
561  _Chain_Extract_unprotected( the_node );
562}
563
564/**
565 * @brief Obtain the first node on a chain.
566 *
567 * This function removes the first node from @a the_chain and returns
568 * a pointer to that node.  If @a the_chain is empty, then NULL is returned.
569 *
570 * @return This method returns a pointer a node.  If a node was removed,
571 *         then a pointer to that node is returned.  If @a the_chain was
572 *         empty, then NULL is returned.
573 *
574 *  NOTE: It disables interrupts to ensure the atomicity of the get operation.
575 */
576RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_get(
577  rtems_chain_control *the_chain
578)
579{
580  return _Chain_Get( the_chain );
581}
582
583/**
584 * @brief See _Chain_Get_unprotected().
585 */
586RTEMS_INLINE_ROUTINE rtems_chain_node *rtems_chain_get_unprotected(
587  rtems_chain_control *the_chain
588)
589{
590  return _Chain_Get_unprotected( the_chain );
591}
592
593/**
594 * @brief Insert a node on a chain
595 *
596 * This routine inserts @a the_node on a chain immediately following
597 * @a after_node. 
598 *
599 * NOTE: It disables interrupts to ensure the atomicity
600 * of the extract operation.
601 */
602RTEMS_INLINE_ROUTINE void rtems_chain_insert(
603  rtems_chain_node *after_node,
604  rtems_chain_node *the_node
605)
606{
607  _Chain_Insert( after_node, the_node );
608}
609
610/**
611 * @brief See _Chain_Insert_unprotected().
612 */
613RTEMS_INLINE_ROUTINE void rtems_chain_insert_unprotected(
614  rtems_chain_node *after_node,
615  rtems_chain_node *the_node
616)
617{
618  _Chain_Insert_unprotected( after_node, the_node );
619}
620
621/**
622 * @brief Append a node on the end of a chain.
623 *
624 * This routine appends @a the_node onto the end of @a the_chain.
625 *
626 * NOTE: It disables interrupts to ensure the atomicity of the
627 * append operation.
628 */
629RTEMS_INLINE_ROUTINE void rtems_chain_append(
630  rtems_chain_control *the_chain,
631  rtems_chain_node    *the_node
632)
633{
634  _Chain_Append( the_chain, the_node );
635}
636
637/**
638 * @brief Append a node on the end of a chain (unprotected).
639 *
640 * This routine appends @a the_node onto the end of @a the_chain.
641 *
642 * NOTE: It does NOT disable interrupts to ensure the atomicity of the
643 * append operation.
644 */
645RTEMS_INLINE_ROUTINE void rtems_chain_append_unprotected(
646  rtems_chain_control *the_chain,
647  rtems_chain_node    *the_node
648)
649{
650  _Chain_Append_unprotected( the_chain, the_node );
651}
652
653/**
654 * @brief Prepend a node.
655 *
656 * This routine prepends the_node onto the front of the_chain.
657 *
658 * @param[in] the_chain is the chain to be operated upon.
659 * @param[in] the_node is the node to be prepended.
660 *
661 * NOTE: It disables interrupts to ensure the atomicity of the
662 *       prepend operation.
663 */
664RTEMS_INLINE_ROUTINE void rtems_chain_prepend(
665  rtems_chain_control *the_chain,
666  rtems_chain_node    *the_node
667)
668{
669  _Chain_Prepend( the_chain, the_node );
670}
671
672/**
673 * @brief Prepend a node (unprotected).
674 *
675 * This routine prepends the_node onto the front of the_chain.
676 *
677 * @param[in] the_chain is the chain to be operated upon.
678 * @param[in] the_node is the node to be prepended.
679 *
680 * NOTE: It does NOT disable interrupts to ensure the atomicity of the
681 *       prepend operation.
682 */
683RTEMS_INLINE_ROUTINE void rtems_chain_prepend_unprotected(
684  rtems_chain_control *the_chain,
685  rtems_chain_node    *the_node
686)
687{
688  _Chain_Prepend_unprotected( the_chain, the_node );
689}
690
691/**
692 * @brief Checks if the @a chain is empty and appends the @a node.
693 *
694 * Interrupts are disabled to ensure the atomicity of the operation.
695 *
696 * @retval true The chain was empty before the append.
697 * @retval false The chain contained at least one node before the append.
698 */
699RTEMS_INLINE_ROUTINE bool rtems_chain_append_with_empty_check(
700  rtems_chain_control *chain,
701  rtems_chain_node *node
702)
703{
704  return _Chain_Append_with_empty_check( chain, node );
705}
706
707/**
708 * @brief Checks if the @a chain is empty and prepends the @a node.
709 *
710 * Interrupts are disabled to ensure the atomicity of the operation.
711 *
712 * @retval true The chain was empty before the prepend.
713 * @retval false The chain contained at least one node before the prepend.
714 */
715RTEMS_INLINE_ROUTINE bool rtems_chain_prepend_with_empty_check(
716  rtems_chain_control *chain,
717  rtems_chain_node *node
718)
719{
720  return _Chain_Prepend_with_empty_check( chain, node );
721}
722
723/**
724 * @brief Tries to get the first @a node and check if the @a chain is empty
725 * afterwards.
726 *
727 * This function removes the first node from the @a chain and returns a pointer
728 * to that node in @a node.  If the @a chain is empty, then @c NULL is returned.
729 *
730 * Interrupts are disabled to ensure the atomicity of the operation.
731 *
732 * @retval true The chain is empty after the node removal.
733 * @retval false The chain contained at least one node after the node removal.
734 */
735RTEMS_INLINE_ROUTINE bool rtems_chain_get_with_empty_check(
736  rtems_chain_control *chain,
737  rtems_chain_node **node
738)
739{
740  return _Chain_Get_with_empty_check( chain, node );
741}
742
743/**
744 * @brief Returns the node count of the chain.
745 *
746 * @param[in] chain The chain.
747 *
748 * @note It does NOT disable interrupts to ensure the atomicity of the
749 * operation.
750 *
751 * @return The node count of the chain.
752 */
753RTEMS_INLINE_ROUTINE size_t rtems_chain_node_count_unprotected(
754  const rtems_chain_control *chain
755)
756{
757  return _Chain_Node_count_unprotected( chain );
758}
759
760/** @} */
761
762#ifdef __cplusplus
763}
764#endif
765
766#endif
767/* end of include file */
Note: See TracBrowser for help on using the repository browser.