RTEMS 7.0-rc1
Loading...
Searching...
No Matches
chainimpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * Copyright (c) 2010 embedded brains GmbH & Co. KG
14 *
15 * COPYRIGHT (c) 1989-2014.
16 * On-Line Applications Research Corporation (OAR).
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#ifndef _RTEMS_SCORE_CHAINIMPL_H
41#define _RTEMS_SCORE_CHAINIMPL_H
42
43#include <rtems/score/chain.h>
44#include <rtems/score/assert.h>
45
46#ifdef __cplusplus
47extern "C" {
48#endif
49
59#define CHAIN_INITIALIZER_EMPTY(name) \
60 { { { &(name).Tail.Node, NULL }, &(name).Head.Node } }
61
67#define CHAIN_INITIALIZER_ONE_NODE( node ) \
68 { { { (node), NULL }, (node) } }
69
75#define CHAIN_NODE_INITIALIZER_ONE_NODE_CHAIN( chain ) \
76 { &(chain)->Tail.Node, &(chain)->Head.Node }
77
81#define CHAIN_DEFINE_EMPTY(name) \
82 Chain_Control name = CHAIN_INITIALIZER_EMPTY(name)
83
98 Chain_Control *the_chain,
99 void *starting_address,
100 size_t number_nodes,
101 size_t node_size
102);
103
114size_t _Chain_Node_count_unprotected( const Chain_Control *chain );
115
124static inline void _Chain_Set_off_chain(
125 Chain_Node *node
126)
127{
128 node->next = NULL;
129#if defined(RTEMS_DEBUG)
130 node->previous = NULL;
131#endif
132}
133
142static inline void _Chain_Initialize_node( Chain_Node *the_node )
143{
144#if defined(RTEMS_DEBUG)
145 _Chain_Set_off_chain( the_node );
146#else
147 (void) the_node;
148#endif
149}
150
162static inline bool _Chain_Is_node_off_chain( const Chain_Node *node )
163{
164 if ( node->next == NULL ) {
165#if defined( RTEMS_DEBUG )
166 return node->previous == NULL;
167#else
168 return true;
169#endif
170 }
171
172 return false;
173}
174
187static inline bool _Chain_Are_nodes_equal(
188 const Chain_Node *left,
189 const Chain_Node *right
190)
191{
192 return left == right;
193}
194
204static inline Chain_Node *_Chain_Head(
205 Chain_Control *the_chain
206)
207{
208 return &the_chain->Head.Node;
209}
210
220static inline const Chain_Node *_Chain_Immutable_head(
221 const Chain_Control *the_chain
222)
223{
224 return &the_chain->Head.Node;
225}
226
236static inline Chain_Node *_Chain_Tail(
237 Chain_Control *the_chain
238)
239{
240 return &the_chain->Tail.Node;
241}
242
252static inline const Chain_Node *_Chain_Immutable_tail(
253 const Chain_Control *the_chain
254)
255{
256 return &the_chain->Tail.Node;
257}
258
269static inline Chain_Node *_Chain_First(
270 const Chain_Control *the_chain
271)
272{
273 return _Chain_Immutable_head( the_chain )->next;
274}
275
286static inline const Chain_Node *_Chain_Immutable_first(
287 const Chain_Control *the_chain
288)
289{
290 return _Chain_Immutable_head( the_chain )->next;
291}
292
303static inline Chain_Node *_Chain_Last(
304 const Chain_Control *the_chain
305)
306{
307 return _Chain_Immutable_tail( the_chain )->previous;
308}
309
320static inline const Chain_Node *_Chain_Immutable_last(
321 const Chain_Control *the_chain
322)
323{
324 return _Chain_Immutable_tail( the_chain )->previous;
325}
326
336static inline Chain_Node *_Chain_Next(
337 const Chain_Node *the_node
338)
339{
340 return the_node->next;
341}
342
352static inline const Chain_Node *_Chain_Immutable_next(
353 const Chain_Node *the_node
354)
355{
356 return the_node->next;
357}
358
368static inline Chain_Node *_Chain_Previous(
369 const Chain_Node *the_node
370)
371{
372 return the_node->previous;
373}
374
384static inline const Chain_Node *_Chain_Immutable_previous(
385 const Chain_Node *the_node
386)
387{
388 return the_node->previous;
389}
390
402static inline bool _Chain_Is_empty(
403 const Chain_Control *the_chain
404)
405{
406 return _Chain_Immutable_first( the_chain )
407 == _Chain_Immutable_tail( the_chain );
408}
409
422static inline bool _Chain_Is_first(
423 const Chain_Node *the_node
424)
425{
426 return (the_node->previous->previous == NULL);
427}
428
441static inline bool _Chain_Is_last(
442 const Chain_Node *the_node
443)
444{
445 return (the_node->next->next == NULL);
446}
447
459static inline bool _Chain_Has_only_one_node(
460 const Chain_Control *the_chain
461)
462{
463 return _Chain_Immutable_first( the_chain )
464 == _Chain_Immutable_last( the_chain );
465}
466
479static inline bool _Chain_Is_head(
480 const Chain_Control *the_chain,
481 const Chain_Node *the_node
482)
483{
484 return (the_node == _Chain_Immutable_head( the_chain ));
485}
486
499static inline bool _Chain_Is_tail(
500 const Chain_Control *the_chain,
501 const Chain_Node *the_node
502)
503{
504 return (the_node == _Chain_Immutable_tail( the_chain ));
505}
506
514static inline void _Chain_Initialize_empty(
515 Chain_Control *the_chain
516)
517{
518 Chain_Node *head;
519 Chain_Node *tail;
520
521 _Assert( the_chain != NULL );
522
523 head = _Chain_Head( the_chain );
524 tail = _Chain_Tail( the_chain );
525
526 head->next = tail;
527 head->previous = NULL;
528 tail->previous = head;
529}
530
537static inline void _Chain_Initialize_one(
538 Chain_Control *the_chain,
539 Chain_Node *the_node
540)
541{
542 Chain_Node *head;
543 Chain_Node *tail;
544
545 _Assert( _Chain_Is_node_off_chain( the_node ) );
546
547 head = _Chain_Head( the_chain );
548 tail = _Chain_Tail( the_chain );
549
550 the_node->next = tail;
551 the_node->previous = head;
552
553 head->next = the_node;
554 head->previous = NULL;
555 tail->previous = the_node;
556}
557
567static inline void _Chain_Extract_unprotected(
568 Chain_Node *the_node
569)
570{
571 Chain_Node *next;
572 Chain_Node *previous;
573
574 _Assert( !_Chain_Is_node_off_chain( the_node ) );
575
576 next = the_node->next;
577 previous = the_node->previous;
578 next->previous = previous;
579 previous->next = next;
580
581#if defined(RTEMS_DEBUG)
582 _Chain_Set_off_chain( the_node );
583#endif
584}
585
601static inline Chain_Node *_Chain_Get_first_unprotected(
602 Chain_Control *the_chain
603)
604{
605 Chain_Node *head;
606 Chain_Node *old_first;
607 Chain_Node *new_first;
608
609 _Assert( !_Chain_Is_empty( the_chain ) );
610
611 head = _Chain_Head( the_chain );
612 old_first = head->next;
613 new_first = old_first->next;
614
615 head->next = new_first;
616 new_first->previous = head;
617
618#if defined(RTEMS_DEBUG)
619 _Chain_Set_off_chain( old_first );
620#endif
621
622 return old_first;
623}
624
639static inline Chain_Node *_Chain_Get_unprotected(
640 Chain_Control *the_chain
641)
642{
643 if ( !_Chain_Is_empty(the_chain))
644 return _Chain_Get_first_unprotected(the_chain);
645 else
646 return NULL;
647}
648
662static inline void _Chain_Insert_unprotected(
663 Chain_Node *after_node,
664 Chain_Node *the_node
665)
666{
667 Chain_Node *before_node;
668
669 _Assert( _Chain_Is_node_off_chain( the_node ) );
670
671 the_node->previous = after_node;
672 before_node = after_node->next;
673 after_node->next = the_node;
674 the_node->next = before_node;
675 before_node->previous = the_node;
676}
677
689static inline void _Chain_Append_unprotected(
690 Chain_Control *the_chain,
691 Chain_Node *the_node
692)
693{
694 Chain_Node *tail;
695 Chain_Node *old_last;
696
697 _Assert( _Chain_Is_node_off_chain( the_node ) );
698
699 tail = _Chain_Tail( the_chain );
700 old_last = tail->previous;
701
702 the_node->next = tail;
703 tail->previous = the_node;
704 old_last->next = the_node;
705 the_node->previous = old_last;
706}
707
720static inline void _Chain_Append_if_is_off_chain_unprotected(
721 Chain_Control *the_chain,
722 Chain_Node *the_node
723)
724{
725 if ( _Chain_Is_node_off_chain( the_node ) ) {
726 _Chain_Append_unprotected( the_chain, the_node );
727 }
728}
729
741static inline void _Chain_Prepend_unprotected(
742 Chain_Control *the_chain,
743 Chain_Node *the_node
744)
745{
746 _Chain_Insert_unprotected(_Chain_Head(the_chain), the_node);
747}
748
763static inline bool _Chain_Append_with_empty_check_unprotected(
764 Chain_Control *the_chain,
765 Chain_Node *the_node
766)
767{
768 bool was_empty = _Chain_Is_empty( the_chain );
769
770 _Chain_Append_unprotected( the_chain, the_node );
771
772 return was_empty;
773}
774
789static inline bool _Chain_Prepend_with_empty_check_unprotected(
790 Chain_Control *the_chain,
791 Chain_Node *the_node
792)
793{
794 bool was_empty = _Chain_Is_empty( the_chain );
795
796 _Chain_Prepend_unprotected( the_chain, the_node );
797
798 return was_empty;
799}
800
819static inline bool _Chain_Get_with_empty_check_unprotected(
820 Chain_Control *the_chain,
821 Chain_Node **the_node
822)
823{
824 bool is_empty_now = true;
825 Chain_Node *head = _Chain_Head( the_chain );
826 Chain_Node *tail = _Chain_Tail( the_chain );
827 Chain_Node *old_first = head->next;
828
829 if ( old_first != tail ) {
830 Chain_Node *new_first = old_first->next;
831
832 head->next = new_first;
833 new_first->previous = head;
834
835 *the_node = old_first;
836
837 is_empty_now = new_first == tail;
838 } else
839 *the_node = NULL;
840
841 return is_empty_now;
842}
843
853typedef bool ( *Chain_Node_order )(
854 const void *key,
855 const Chain_Node *left,
856 const Chain_Node *right
857);
858
874static inline void _Chain_Insert_ordered_unprotected(
875 Chain_Control *the_chain,
876 Chain_Node *to_insert,
877 const void *key,
878 Chain_Node_order order
879)
880{
881 const Chain_Node *tail = _Chain_Immutable_tail( the_chain );
882 Chain_Node *previous = _Chain_Head( the_chain );
883 Chain_Node *next = _Chain_First( the_chain );
884
885 while ( next != tail && !( *order )( key, to_insert, next ) ) {
886 previous = next;
887 next = _Chain_Next( next );
888 }
889
890 _Chain_Insert_unprotected( previous, to_insert );
891}
892
896typedef enum {
901
907
914typedef struct {
921
928
939
946typedef struct {
947 Chain_Control Iterators;
949
955#define CHAIN_ITERATOR_REGISTRY_INITIALIZER( name ) \
956 { CHAIN_INITIALIZER_EMPTY( name.Iterators ) }
957
963static inline void _Chain_Iterator_registry_initialize(
964 Chain_Iterator_registry *the_registry
965)
966{
967 _Chain_Initialize_empty( &the_registry->Iterators );
968}
969
982static inline void _Chain_Iterator_registry_update(
983 Chain_Iterator_registry *the_registry,
984 Chain_Node *the_node_to_extract
985)
986{
987 Chain_Node *iter_node;
988 Chain_Node *iter_tail;
989
990 iter_node = _Chain_Head( &the_registry->Iterators );
991 iter_tail = _Chain_Tail( &the_registry->Iterators );
992
993 while ( ( iter_node = _Chain_Next( iter_node ) ) != iter_tail ) {
994 Chain_Iterator *iter;
995
996 iter = (Chain_Iterator *) iter_node;
997
998 if ( iter->position == the_node_to_extract ) {
999 if ( iter->direction == CHAIN_ITERATOR_FORWARD ) {
1000 iter->position = _Chain_Previous( the_node_to_extract );
1001 } else {
1002 iter->position = _Chain_Next( the_node_to_extract );
1003 }
1004 }
1005 }
1006}
1007
1071static inline void _Chain_Iterator_initialize(
1072 Chain_Control *the_chain,
1073 Chain_Iterator_registry *the_registry,
1074 Chain_Iterator *the_iterator,
1075 Chain_Iterator_direction direction
1076)
1077{
1078 _Chain_Initialize_node( &the_iterator->Registry_node );
1079 _Chain_Append_unprotected(
1080 &the_registry->Iterators,
1081 &the_iterator->Registry_node
1082 );
1083
1084 the_iterator->direction = direction;
1085
1086 if ( direction == CHAIN_ITERATOR_FORWARD ) {
1087 the_iterator->position = _Chain_Head( the_chain );
1088 } else {
1089 the_iterator->position = _Chain_Tail( the_chain );
1090 }
1091}
1092
1103static inline Chain_Node *_Chain_Iterator_next(
1104 const Chain_Iterator *the_iterator
1105)
1106{
1107 if ( the_iterator->direction == CHAIN_ITERATOR_FORWARD ) {
1108 return _Chain_Next( the_iterator->position );
1109 } else {
1110 return _Chain_Previous( the_iterator->position );
1111 }
1112}
1113
1120static inline void _Chain_Iterator_set_position(
1121 Chain_Iterator *the_iterator,
1122 Chain_Node *the_node
1123)
1124{
1125 the_iterator->position = the_node;
1126}
1127
1135static inline void _Chain_Iterator_destroy(
1136 Chain_Iterator *the_iterator
1137)
1138{
1139 _Chain_Extract_unprotected( &the_iterator->Registry_node );
1140}
1141
1144#ifdef __cplusplus
1145}
1146#endif
1147
1148#endif
1149/* end of include file */
This header file provides the interfaces of the Assert Handler.
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG and static analysis runs.
Definition: assert.h:96
size_t _Chain_Node_count_unprotected(const Chain_Control *chain)
Returns the node count of the chain.
Definition: chainnodecount.c:42
void _Chain_Initialize(Chain_Control *the_chain, void *starting_address, size_t number_nodes, size_t node_size)
Initializes a chain header.
Definition: chain.c:46
bool(* Chain_Node_order)(const void *key, const Chain_Node *left, const Chain_Node *right)
Chain node order.
Definition: chainimpl.h:853
Chain_Iterator_direction
The chain iterator direction.
Definition: chainimpl.h:896
@ CHAIN_ITERATOR_BACKWARD
Iteration from tail to head.
Definition: chainimpl.h:905
@ CHAIN_ITERATOR_FORWARD
Iteration from head to tail.
Definition: chainimpl.h:900
This header file provides interfaces of the Chain Handler which are used by the implementation and th...
A registry for chain iterators.
Definition: chainimpl.h:946
A chain iterator which is updated during node extraction if it is properly registered.
Definition: chainimpl.h:914
Chain_Node * position
The current position of this iterator.
Definition: chainimpl.h:937
Chain_Node Registry_node
Node for registration.
Definition: chainimpl.h:920
Chain_Iterator_direction direction
The direction of this iterator.
Definition: chainimpl.h:927
This structure represents a chain node.
Definition: chain.h:78
struct Chain_Node * next
Definition: chain.h:80
struct Chain_Node * previous
Definition: chain.h:82
This union represents a chain control block.
Definition: chain.h:96