source: rtems/cpukit/score/include/rtems/score/chainimpl.h @ c130387

5
Last change on this file since c130387 was c130387, checked in by Sebastian Huber <sebastian.huber@…>, on 04/04/16 at 07:24:47

score: Delete _Chain_Prepend_with_empty_check()

This function is not used in the score.

Update #2555.

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