source: rtems/cpukit/score/include/rtems/score/chainimpl.h @ 8e7db68c

4.115
Last change on this file since 8e7db68c was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 24.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief Chain Handler API
5 */
6
7/*
8 *  Copyright (c) 2010 embedded brains GmbH.
9 *
10 *  COPYRIGHT (c) 1989-2006.
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.org/license/LICENSE.
16 */
17
18#ifndef _RTEMS_SCORE_CHAINIMPL_H
19#define _RTEMS_SCORE_CHAINIMPL_H
20
21#include <rtems/score/chain.h>
22#include <rtems/score/address.h>
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/**
29 * @addtogroup ScoreChain
30 */
31/**@{**/
32
33/**
34 *  @brief Chain initializer for an empty chain with designator @a name.
35 */
36#define CHAIN_INITIALIZER_EMPTY(name) \
37  { { { &(name).Tail.Node, NULL }, &(name).Head.Node } }
38
39/**
40 *  @brief Chain initializer for a chain with one @a node.
41 *
42 *  @see CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN().
43 */
44#define CHAIN_INITIALIZER_ONE_NODE( node ) \
45  { { { (node), NULL }, (node) } }
46
47/**
48 *  @brief Chain node initializer for a @a chain containing exactly this node.
49 *
50 *  @see CHAIN_INITIALIZER_ONE_NODE().
51 */
52#define CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN( chain ) \
53  { &(chain)->Tail.Node, &(chain)->Head.Node }
54
55/**
56 *  @brief Chain definition for an empty chain with designator @a name.
57 */
58#define CHAIN_DEFINE_EMPTY(name) \
59  Chain_Control name = CHAIN_INITIALIZER_EMPTY(name)
60
61/**
62 *  @brief Initialize a chain header.
63 *
64 *  This routine initializes @a the_chain structure to manage the
65 *  contiguous array of @a number_nodes nodes which starts at
66 *  @a starting_address.  Each node is of @a node_size bytes.
67 *
68 *  @param[in] the_chain specifies the chain to initialize
69 *  @param[in] starting_address is the starting address of the array
70 *         of elements
71 *  @param[in] number_nodes is the numebr of nodes that will be in the chain
72 *  @param[in] node_size is the size of each node
73 */
74void _Chain_Initialize(
75  Chain_Control *the_chain,
76  void          *starting_address,
77  size_t         number_nodes,
78  size_t         node_size
79);
80
81/**
82 *  @brief Extract the specified node from a chain.
83 *
84 *  This routine extracts @a the_node from the chain on which it resides.
85 *  It disables interrupts to ensure the atomicity of the extract operation.
86 *
87 *  @param[in] the_node is the node to be extracted
88 *
89 *  - INTERRUPT LATENCY:
90 *    + single case
91 */
92void _Chain_Extract(
93  Chain_Node *the_node
94);
95
96/**
97 *  @brief Obtain the first node on a chain.
98 *
99 *  This function removes the first node from @a the_chain and returns
100 *  a pointer to that node.  If @a the_chain is empty, then NULL is returned.
101 *
102 *  @retval This method returns a pointer a node.  If a node was removed,
103 *          then a pointer to that node is returned.  If @a the_chain was
104 *          empty, then NULL is returned.
105 *
106 *  @note It disables interrupts to ensure the atomicity of the get operation.
107 */
108Chain_Node *_Chain_Get(
109  Chain_Control *the_chain
110);
111
112/**
113 *  @brief Insert a node on a chain.
114 *
115 *  This routine inserts @a the_node on a chain immediately following
116 *  @a after_node.
117 *
118 *  @param[in] after_node is the pointer to the node in chain to be
119 *             inserted after
120 *  @param[in] the_node is the pointer to the node to be inserted
121 *
122 *  @note It disables interrupts to ensure the atomicity
123 *  of the insert operation.
124 *
125 *  - INTERRUPT LATENCY:
126 *    + single case
127 */
128void _Chain_Insert(
129  Chain_Node *after_node,
130  Chain_Node *the_node
131);
132
133/**
134 *  @brief Append a node on the end of a chain.
135 *
136 *  This routine appends @a the_node onto the end of @a the_chain.
137 *
138 *  @note It disables interrupts to ensure the atomicity of the
139 *  append operation.
140 */
141void _Chain_Append(
142  Chain_Control *the_chain,
143  Chain_Node    *the_node
144);
145
146/**
147 * @brief Append a node and check if the chain was empty before.
148 *
149 * This routine appends the_node onto the end of the_chain.
150 *
151 * @param[in] the_chain is the chain to be operated upon.
152 * @param[in] the_node is the node to be appended.
153 *
154 * @note It disables interrupts to ensure the atomicity of the append
155 * operation.
156 *
157 * @retval true The chain was empty before.
158 * @retval false The chain contained at least one node before.
159 */
160bool _Chain_Append_with_empty_check(
161  Chain_Control *the_chain,
162  Chain_Node    *the_node
163);
164
165/**
166 * @brief Prepend a node and check if the chain was empty before.
167 *
168 * This routine prepends the_node onto the front of the_chain.
169 *
170 * @param[in] the_chain is the chain to be operated upon.
171 * @param[in] the_node is the node to be prepended.
172 *
173 * @note It disables interrupts to ensure the atomicity of the append
174 * operation.
175 *
176 * @retval true The chain was empty before.
177 * @retval false The chain contained at least one node before.
178 */
179bool _Chain_Prepend_with_empty_check(
180  Chain_Control *the_chain,
181  Chain_Node    *the_node
182);
183
184/**
185 * @brief Get the first node and check if the chain is empty afterwards.
186 *
187 * This function removes the first node from the_chain and returns
188 * a pointer to that node in @a the_node.  If the_chain is empty, then NULL is
189 * returned.
190 *
191 * @param[in] the_chain is the chain to attempt to get the first node from.
192 * @param[out] the_node is the first node on the chain or NULL if the chain is
193 * empty.
194 *
195 * @note It disables interrupts to ensure the atomicity of the append
196 * operation.
197 *
198 * @retval true The chain is empty now.
199 * @retval false The chain contains at least one node now.
200 *
201 *  - INTERRUPT LATENCY:
202 *    + single case
203 */
204bool _Chain_Get_with_empty_check(
205  Chain_Control *the_chain,
206  Chain_Node **the_node
207);
208
209/**
210 * @brief Returns the node count of the chain.
211 *
212 * @param[in] chain The chain.
213 *
214 * @note It does NOT disable interrupts to ensure the atomicity of the
215 * operation.
216 *
217 * @retval The node count of the chain.
218 */
219size_t _Chain_Node_count_unprotected( const Chain_Control *chain );
220
221/**
222 * @brief Set off chain.
223 *
224 * This function sets the next field of the @a node to NULL indicating the @a
225 * node is not part of a chain.
226 *
227 * @param[in] node the node set to off chain.
228 */
229RTEMS_INLINE_ROUTINE void _Chain_Set_off_chain(
230  Chain_Node *node
231)
232{
233  node->next = NULL;
234}
235
236/**
237 * @brief Is the node off chain.
238 *
239 * This function returns true if the @a node is not on a chain.  A @a node is
240 * off chain if the next field is set to NULL.
241 *
242 * @param[in] node is the node off chain.
243 *
244 * @retval true The @a node is off chain.
245 * @retval false The @a node is not off chain.
246 */
247RTEMS_INLINE_ROUTINE bool _Chain_Is_node_off_chain(
248  const Chain_Node *node
249)
250{
251  return node->next == NULL;
252}
253
254/**
255 * @brief Are two nodes equal.
256 *
257 * This function returns true if @a left and @a right are equal,
258 * and false otherwise.
259 *
260 * @param[in] left is the node on the left hand side of the comparison.
261 * @param[in] right is the node on the left hand side of the comparison.
262 *
263 * @retval true @a left and @a right are equal.
264 * @retval false @a left and @a right are not equal.
265 */
266RTEMS_INLINE_ROUTINE bool _Chain_Are_nodes_equal(
267  const Chain_Node *left,
268  const Chain_Node *right
269)
270{
271  return left == right;
272}
273
274/**
275 * @brief Is this chain control pointer NULL.
276 *
277 * This function returns true if the_chain is NULL and false otherwise.
278 *
279 * @param[in] the_chain is the chain to be checked for empty status.
280 *
281 * @retval true @a the_chain is @c NULL.
282 * @retval false @a the_chain is not @c NULL.
283 */
284RTEMS_INLINE_ROUTINE bool _Chain_Is_null(
285  const Chain_Control *the_chain
286)
287{
288  return (the_chain == NULL);
289}
290
291/**
292 * @brief Is the chain node pointer NULL.
293 *
294 * This function returns true if the_node is NULL and false otherwise.
295 *
296 * @param[in] the_node is the node pointer to check.
297 *
298 * @retval true @a the_node is @c NULL.
299 * @retval false @a the_node is not @c NULL.
300 */
301RTEMS_INLINE_ROUTINE bool _Chain_Is_null_node(
302  const Chain_Node *the_node
303)
304{
305  return (the_node == NULL);
306}
307
308/**
309 * @brief Return pointer to chain head.
310 *
311 * This function returns a pointer to the head node on the chain.
312 *
313 * @param[in] the_chain is the chain to be operated upon.
314 *
315 * @return This method returns the permanent head node of the chain.
316 */
317RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Head(
318  Chain_Control *the_chain
319)
320{
321  return &the_chain->Head.Node;
322}
323
324/**
325 * @brief Return pointer to immutable chain head.
326 *
327 * This function returns a pointer to the head node on the chain.
328 *
329 * @param[in] the_chain is the chain to be operated upon.
330 *
331 * @return This method returns the permanent head node of the chain.
332 */
333RTEMS_INLINE_ROUTINE const Chain_Node *_Chain_Immutable_head(
334  const Chain_Control *the_chain
335)
336{
337  return &the_chain->Head.Node;
338}
339
340/**
341 * @brief Return pointer to chain tail.
342 *
343 * This function returns a pointer to the tail node on the chain.
344 *
345 * @param[in] the_chain is the chain to be operated upon.
346 *
347 * @return This method returns the permanent tail node of the chain.
348 */
349RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Tail(
350  Chain_Control *the_chain
351)
352{
353  return &the_chain->Tail.Node;
354}
355
356/**
357 * @brief Return pointer to immutable chain tail.
358 *
359 * This function returns a pointer to the tail node on the chain.
360 *
361 * @param[in] the_chain is the chain to be operated upon.
362 *
363 * @return This method returns the permanent tail node of the chain.
364 */
365RTEMS_INLINE_ROUTINE const Chain_Node *_Chain_Immutable_tail(
366  const Chain_Control *the_chain
367)
368{
369  return &the_chain->Tail.Node;
370}
371
372/**
373 * @brief Return pointer to chain's first node.
374 *
375 * This function returns a pointer to the first node on the chain after the
376 * head.
377 *
378 * @param[in] the_chain is the chain to be operated upon.
379 *
380 * @return This method returns the first node of the chain.
381 */
382RTEMS_INLINE_ROUTINE Chain_Node *_Chain_First(
383  Chain_Control *the_chain
384)
385{
386  return _Chain_Head( the_chain )->next;
387}
388
389/**
390 * @brief Return pointer to immutable chain's first node.
391 *
392 * This function returns a pointer to the first node on the chain after the
393 * head.
394 *
395 * @param[in] the_chain is the chain to be operated upon.
396 *
397 * @return This method returns the first node of the chain.
398 */
399RTEMS_INLINE_ROUTINE const Chain_Node *_Chain_Immutable_first(
400  const Chain_Control *the_chain
401)
402{
403  return _Chain_Immutable_head( the_chain )->next;
404}
405
406/**
407 * @brief Return pointer to chain's last node.
408 *
409 * This function returns a pointer to the last node on the chain just before
410 * the tail.
411 *
412 * @param[in] the_chain is the chain to be operated upon.
413 *
414 * @return This method returns the last node of the chain.
415 */
416RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Last(
417  Chain_Control *the_chain
418)
419{
420  return _Chain_Tail( the_chain )->previous;
421}
422
423/**
424 * @brief Return pointer to immutable chain's last node.
425 *
426 * This function returns a pointer to the last node on the chain just before
427 * the tail.
428 *
429 * @param[in] the_chain is the chain to be operated upon.
430 *
431 * @return This method returns the last node of the chain.
432 */
433RTEMS_INLINE_ROUTINE const Chain_Node *_Chain_Immutable_last(
434  const Chain_Control *the_chain
435)
436{
437  return _Chain_Immutable_tail( the_chain )->previous;
438}
439
440/**
441 * @brief Return pointer the next node from this node.
442 *
443 * This function returns a pointer to the next node after this node.
444 *
445 * @param[in] the_node is the node to be operated upon.
446 *
447 * @return This method returns the next node on the chain.
448 */
449RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Next(
450  Chain_Node *the_node
451)
452{
453  return the_node->next;
454}
455
456/**
457 * @brief Return pointer the immutable next node from this node.
458 *
459 * This function returns a pointer to the next node after this node.
460 *
461 * @param[in] the_node is the node to be operated upon.
462 *
463 * @return This method returns the next node on the chain.
464 */
465RTEMS_INLINE_ROUTINE const Chain_Node *_Chain_Immutable_next(
466  const Chain_Node *the_node
467)
468{
469  return the_node->next;
470}
471
472/**
473 * @brief Return pointer the previous node from this node.
474 *
475 * This function returns a pointer to the previous node on this chain.
476 *
477 * @param[in] the_node is the node to be operated upon.
478 *
479 * @return This method returns the previous node on the chain.
480 */
481RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Previous(
482  Chain_Node *the_node
483)
484{
485  return the_node->previous;
486}
487
488/**
489 * @brief Return pointer the immutable previous node from this node.
490 *
491 * This function returns a pointer to the previous node on this chain.
492 *
493 * @param[in] the_node is the node to be operated upon.
494 *
495 * @return This method returns the previous node on the chain.
496 */
497RTEMS_INLINE_ROUTINE const Chain_Node *_Chain_Immutable_previous(
498  const Chain_Node *the_node
499)
500{
501  return the_node->previous;
502}
503
504/**
505 * @brief Is the chain empty.
506 *
507 * This function returns true if there a no nodes on @a the_chain and
508 * false otherwise.
509 *
510 * @param[in] the_chain is the chain to be operated upon.
511 *
512 * @retval true There are no nodes on @a the_chain.
513 * @retval false There are nodes on @a the_chain.
514 */
515RTEMS_INLINE_ROUTINE bool _Chain_Is_empty(
516  const Chain_Control *the_chain
517)
518{
519  return _Chain_Immutable_first( the_chain )
520    == _Chain_Immutable_tail( the_chain );
521}
522
523/**
524 * @brief Is this the first node on the chain.
525 *
526 * This function returns true if the_node is the first node on a chain and
527 * false otherwise.
528 *
529 * @param[in] the_node is the node the caller wants to know if it is
530 *            the first node on a chain.
531 *
532 * @retval true @a the_node is the first node on a chain.
533 * @retval false @a the_node is not the first node on a chain.
534 */
535RTEMS_INLINE_ROUTINE bool _Chain_Is_first(
536  const Chain_Node *the_node
537)
538{
539  return (the_node->previous->previous == NULL);
540}
541
542/**
543 * @brief Is this the last node on the chain.
544 *
545 * This function returns true if @a the_node is the last node on a chain and
546 * false otherwise.
547 *
548 * @param[in] the_node is the node to check as the last node.
549 *
550 * @retval true @a the_node is the last node on a chain.
551 * @retval false @a the_node is not the last node on a chain.
552 */
553RTEMS_INLINE_ROUTINE bool _Chain_Is_last(
554  const Chain_Node *the_node
555)
556{
557  return (the_node->next->next == NULL);
558}
559
560/**
561 * @brief Does this chain have only one node.
562 *
563 * This function returns true if there is only one node on @a the_chain and
564 * false otherwise.
565 *
566 * @param[in] the_chain is the chain to be operated upon.
567 *
568 * @return This function returns true if there is only one node on
569 *         @a the_chain and false otherwise.
570 *
571 * @retval true There is only one node on @a the_chain.
572 * @retval false There is more than one node on @a the_chain.
573 */
574RTEMS_INLINE_ROUTINE bool _Chain_Has_only_one_node(
575  const Chain_Control *the_chain
576)
577{
578  return _Chain_Immutable_first( the_chain )
579    == _Chain_Immutable_last( the_chain );
580}
581
582/**
583 * @brief Is this node the chain head.
584 *
585 * This function returns true if @a the_node is the head of @a the_chain and
586 * false otherwise.
587 *
588 * @param[in] the_chain is the chain to be operated upon.
589 * @param[in] the_node is the node to check for being the Chain Head.
590 *
591 * @retval true @a the_node is the head of @a the_chain.
592 * @retval false @a the_node is not the head of @a the_chain.
593 */
594RTEMS_INLINE_ROUTINE bool _Chain_Is_head(
595  const Chain_Control *the_chain,
596  const Chain_Node    *the_node
597)
598{
599  return (the_node == _Chain_Immutable_head( the_chain ));
600}
601
602/**
603 * @brief Is this node the chail tail.
604 *
605 * This function returns true if @a the_node is the tail of @a the_chain and
606 * false otherwise.
607 *
608 * @param[in] the_chain is the chain to be operated upon.
609 * @param[in] the_node is the node to check for being the Chain Tail.
610 *
611 * @retval true @a the_node is the tail of @a the_chain.
612 * @retval false @a the_node is not the tail of @a the_chain.
613 */
614RTEMS_INLINE_ROUTINE bool _Chain_Is_tail(
615  const Chain_Control *the_chain,
616  const Chain_Node    *the_node
617)
618{
619  return (the_node == _Chain_Immutable_tail( the_chain ));
620}
621
622/**
623 * @brief Initialize this chain as empty.
624 *
625 * This routine initializes the specified chain to contain zero nodes.
626 *
627 * @param[in] the_chain is the chain to be initialized.
628 */
629RTEMS_INLINE_ROUTINE void _Chain_Initialize_empty(
630  Chain_Control *the_chain
631)
632{
633  Chain_Node *head = _Chain_Head( the_chain );
634  Chain_Node *tail = _Chain_Tail( the_chain );
635
636  head->next = tail;
637  head->previous = NULL;
638  tail->previous = head;
639}
640
641/**
642 * @brief Extract this node (unprotected).
643 *
644 * This routine extracts the_node from the chain on which it resides.
645 * It does NOT disable interrupts to ensure the atomicity of the
646 * extract operation.
647 *
648 * @param[in] the_node is the node to be extracted.
649 */
650RTEMS_INLINE_ROUTINE void _Chain_Extract_unprotected(
651  Chain_Node *the_node
652)
653{
654  Chain_Node *next;
655  Chain_Node *previous;
656
657  next           = the_node->next;
658  previous       = the_node->previous;
659  next->previous = previous;
660  previous->next = next;
661}
662
663/**
664 * @brief Get the first node (unprotected).
665 *
666 * This function removes the first node from the_chain and returns
667 * a pointer to that node.  It does NOT disable interrupts to ensure
668 * the atomicity of the get operation.
669 *
670 * @param[in] the_chain is the chain to attempt to get the first node from.
671 *
672 * @return This method returns the first node on the chain even if it is
673 *         the Chain Tail.
674 *
675 * @note This routine assumes that there is at least one node on the chain
676 *       and always returns a node even if it is the Chain Tail.
677 */
678RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Get_first_unprotected(
679  Chain_Control *the_chain
680)
681{
682  Chain_Node *head = _Chain_Head( the_chain );
683  Chain_Node *old_first = head->next;
684  Chain_Node *new_first = old_first->next;
685
686  head->next = new_first;
687  new_first->previous = head;
688
689  return old_first;
690}
691
692/**
693 * @brief Get the first node (unprotected).
694 *
695 * This function removes the first node from the_chain and returns
696 * a pointer to that node.  If the_chain is empty, then NULL is returned.
697 *
698 * @param[in] the_chain is the chain to attempt to get the first node from.
699 *
700 * @return This method returns the first node on the chain or NULL if the
701 *         chain is empty.
702 *
703 * @note It does NOT disable interrupts to ensure the atomicity of the
704 *       get operation.
705 */
706RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Get_unprotected(
707  Chain_Control *the_chain
708)
709{
710  if ( !_Chain_Is_empty(the_chain))
711    return _Chain_Get_first_unprotected(the_chain);
712  else
713    return NULL;
714}
715
716/**
717 * @brief Insert a node (unprotected).
718 *
719 * This routine inserts the_node on a chain immediately following
720 * after_node.
721 *
722 * @param[in] after_node is the node which will precede @a the_node on the
723 *            chain.
724 * @param[in] the_node is the node to be inserted.
725 *
726 * @note It does NOT disable interrupts to ensure the atomicity
727 *       of the extract operation.
728 */
729RTEMS_INLINE_ROUTINE void _Chain_Insert_unprotected(
730  Chain_Node *after_node,
731  Chain_Node *the_node
732)
733{
734  Chain_Node *before_node;
735
736  the_node->previous    = after_node;
737  before_node           = after_node->next;
738  after_node->next      = the_node;
739  the_node->next        = before_node;
740  before_node->previous = the_node;
741}
742
743/**
744 * @brief Append a node (unprotected).
745 *
746 * This routine appends the_node onto the end of the_chain.
747 *
748 * @param[in] the_chain is the chain to be operated upon.
749 * @param[in] the_node is the node to be appended.
750 *
751 * @note It does NOT disable interrupts to ensure the atomicity of the
752 *       append operation.
753 */
754RTEMS_INLINE_ROUTINE void _Chain_Append_unprotected(
755  Chain_Control *the_chain,
756  Chain_Node    *the_node
757)
758{
759  Chain_Node *tail = _Chain_Tail( the_chain );
760  Chain_Node *old_last = tail->previous;
761
762  the_node->next = tail;
763  tail->previous = the_node;
764  old_last->next = the_node;
765  the_node->previous = old_last;
766}
767
768/**
769 * @brief Append a node on the end of a chain if the node is in the off chain
770 * state (unprotected).
771 *
772 * @note It does NOT disable interrupts to ensure the atomicity of the
773 *       append operation.
774 *
775 * @see _Chain_Append_unprotected() and _Chain_Is_node_off_chain().
776 */
777RTEMS_INLINE_ROUTINE void _Chain_Append_if_is_off_chain_unprotected(
778  Chain_Control *the_chain,
779  Chain_Node    *the_node
780)
781{
782  if ( _Chain_Is_node_off_chain( the_node ) ) {
783    _Chain_Append_unprotected( the_chain, the_node );
784  }
785}
786
787/**
788 * @brief Prepend a node (unprotected).
789 *
790 * This routine prepends the_node onto the front of the_chain.
791 *
792 * @param[in] the_chain is the chain to be operated upon.
793 * @param[in] the_node is the node to be prepended.
794 *
795 * @note It does NOT disable interrupts to ensure the atomicity of the
796 *       prepend operation.
797 */
798RTEMS_INLINE_ROUTINE void _Chain_Prepend_unprotected(
799  Chain_Control *the_chain,
800  Chain_Node    *the_node
801)
802{
803  _Chain_Insert_unprotected(_Chain_Head(the_chain), the_node);
804}
805
806/**
807 * @brief Prepend a node (protected).
808 *
809 * This routine prepends the_node onto the front of the_chain.
810 *
811 * @param[in] the_chain is the chain to be operated upon.
812 * @param[in] the_node is the node to be prepended.
813 *
814 * @note It disables interrupts to ensure the atomicity of the
815 *       prepend operation.
816 */
817RTEMS_INLINE_ROUTINE void _Chain_Prepend(
818  Chain_Control *the_chain,
819  Chain_Node    *the_node
820)
821{
822  _Chain_Insert(_Chain_Head(the_chain), the_node);
823}
824
825/**
826 * @brief Append a node and check if the chain was empty before (unprotected).
827 *
828 * This routine appends the_node onto the end of the_chain.
829 *
830 * @param[in] the_chain is the chain to be operated upon.
831 * @param[in] the_node is the node to be appended.
832 *
833 * @note It does NOT disable interrupts to ensure the atomicity of the
834 *       append operation.
835 *
836 * @retval true The chain was empty before.
837 * @retval false The chain contained at least one node before.
838 */
839RTEMS_INLINE_ROUTINE bool _Chain_Append_with_empty_check_unprotected(
840  Chain_Control *the_chain,
841  Chain_Node    *the_node
842)
843{
844  bool was_empty = _Chain_Is_empty( the_chain );
845
846  _Chain_Append_unprotected( the_chain, the_node );
847
848  return was_empty;
849}
850
851/**
852 * @brief Prepend a node and check if the chain was empty before (unprotected).
853 *
854 * This routine prepends the_node onto the front of the_chain.
855 *
856 * @param[in] the_chain is the chain to be operated upon.
857 * @param[in] the_node is the node to be prepended.
858 *
859 * @note It does NOT disable interrupts to ensure the atomicity of the
860 *       prepend operation.
861 *
862 * @retval true The chain was empty before.
863 * @retval false The chain contained at least one node before.
864 */
865RTEMS_INLINE_ROUTINE bool _Chain_Prepend_with_empty_check_unprotected(
866  Chain_Control *the_chain,
867  Chain_Node    *the_node
868)
869{
870  bool was_empty = _Chain_Is_empty( the_chain );
871
872  _Chain_Prepend_unprotected( the_chain, the_node );
873
874  return was_empty;
875}
876
877/**
878 * @brief Get the first node and check if the chain is empty afterwards
879 * (unprotected).
880 *
881 * This function removes the first node from the_chain and returns
882 * a pointer to that node in @a the_node.  If the_chain is empty, then NULL is
883 * returned.
884 *
885 * @param[in] the_chain is the chain to attempt to get the first node from.
886 * @param[out] the_node is the first node on the chain or NULL if the chain is
887 * empty.
888 *
889 * @note It does NOT disable interrupts to ensure the atomicity of the
890 *       get operation.
891 *
892 * @retval true The chain is empty now.
893 * @retval false The chain contains at least one node now.
894 */
895RTEMS_INLINE_ROUTINE bool _Chain_Get_with_empty_check_unprotected(
896  Chain_Control *the_chain,
897  Chain_Node **the_node
898)
899{
900  bool is_empty_now = true;
901  Chain_Node *head = _Chain_Head( the_chain );
902  Chain_Node *tail = _Chain_Tail( the_chain );
903  Chain_Node *old_first = head->next;
904
905  if ( old_first != tail ) {
906    Chain_Node *new_first = old_first->next;
907
908    head->next = new_first;
909    new_first->previous = head;
910
911    *the_node = old_first;
912
913    is_empty_now = new_first == tail;
914  } else
915    *the_node = NULL;
916
917  return is_empty_now;
918}
919
920/**
921 * @brief Chain node order.
922 *
923 * @param[in] left The left node.
924 * @param[in] right The right node.
925 *
926 * @retval true According to the order the left node precedes the right node.
927 * @retval false Otherwise.
928 */
929typedef bool ( *Chain_Node_order )(
930  const Chain_Node *left,
931  const Chain_Node *right
932);
933
934/**
935 * @brief Inserts a node into the chain according to the order relation.
936 *
937 * After the operation the chain contains the node to insert and the order
938 * relation holds for all nodes from the head up to the inserted node.  Nodes
939 * after the inserted node are not moved.
940 *
941 * @param[in,out] chain The chain.
942 * @param[in,out] to_insert The node to insert.
943 * @param[in] order The order relation.
944 */
945RTEMS_INLINE_ROUTINE void _Chain_Insert_ordered_unprotected(
946  Chain_Control *chain,
947  Chain_Node *to_insert,
948  Chain_Node_order order
949)
950{
951  const Chain_Node *tail = _Chain_Immutable_tail( chain );
952  Chain_Node *next = _Chain_First( chain );
953
954  while ( next != tail && !( *order )( to_insert, next ) ) {
955    next = _Chain_Next( next );
956  }
957
958  _Chain_Insert_unprotected( _Chain_Previous( next ), to_insert );
959}
960
961/** @} */
962
963#ifdef __cplusplus
964}
965#endif
966
967#endif
968/* end of include file */
Note: See TracBrowser for help on using the repository browser.