RTEMS 6.1-rc1
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(
163 const Chain_Node *node
164)
165{
166 return node->next == NULL;
167}
168
181static inline bool _Chain_Are_nodes_equal(
182 const Chain_Node *left,
183 const Chain_Node *right
184)
185{
186 return left == right;
187}
188
198static inline Chain_Node *_Chain_Head(
199 Chain_Control *the_chain
200)
201{
202 return &the_chain->Head.Node;
203}
204
214static inline const Chain_Node *_Chain_Immutable_head(
215 const Chain_Control *the_chain
216)
217{
218 return &the_chain->Head.Node;
219}
220
230static inline Chain_Node *_Chain_Tail(
231 Chain_Control *the_chain
232)
233{
234 return &the_chain->Tail.Node;
235}
236
246static inline const Chain_Node *_Chain_Immutable_tail(
247 const Chain_Control *the_chain
248)
249{
250 return &the_chain->Tail.Node;
251}
252
263static inline Chain_Node *_Chain_First(
264 const Chain_Control *the_chain
265)
266{
267 return _Chain_Immutable_head( the_chain )->next;
268}
269
280static inline const Chain_Node *_Chain_Immutable_first(
281 const Chain_Control *the_chain
282)
283{
284 return _Chain_Immutable_head( the_chain )->next;
285}
286
297static inline Chain_Node *_Chain_Last(
298 const Chain_Control *the_chain
299)
300{
301 return _Chain_Immutable_tail( the_chain )->previous;
302}
303
314static inline const Chain_Node *_Chain_Immutable_last(
315 const Chain_Control *the_chain
316)
317{
318 return _Chain_Immutable_tail( the_chain )->previous;
319}
320
330static inline Chain_Node *_Chain_Next(
331 const Chain_Node *the_node
332)
333{
334 return the_node->next;
335}
336
346static inline const Chain_Node *_Chain_Immutable_next(
347 const Chain_Node *the_node
348)
349{
350 return the_node->next;
351}
352
362static inline Chain_Node *_Chain_Previous(
363 const Chain_Node *the_node
364)
365{
366 return the_node->previous;
367}
368
378static inline const Chain_Node *_Chain_Immutable_previous(
379 const Chain_Node *the_node
380)
381{
382 return the_node->previous;
383}
384
396static inline bool _Chain_Is_empty(
397 const Chain_Control *the_chain
398)
399{
400 return _Chain_Immutable_first( the_chain )
401 == _Chain_Immutable_tail( the_chain );
402}
403
416static inline bool _Chain_Is_first(
417 const Chain_Node *the_node
418)
419{
420 return (the_node->previous->previous == NULL);
421}
422
435static inline bool _Chain_Is_last(
436 const Chain_Node *the_node
437)
438{
439 return (the_node->next->next == NULL);
440}
441
453static inline bool _Chain_Has_only_one_node(
454 const Chain_Control *the_chain
455)
456{
457 return _Chain_Immutable_first( the_chain )
458 == _Chain_Immutable_last( the_chain );
459}
460
473static inline bool _Chain_Is_head(
474 const Chain_Control *the_chain,
475 const Chain_Node *the_node
476)
477{
478 return (the_node == _Chain_Immutable_head( the_chain ));
479}
480
493static inline bool _Chain_Is_tail(
494 const Chain_Control *the_chain,
495 const Chain_Node *the_node
496)
497{
498 return (the_node == _Chain_Immutable_tail( the_chain ));
499}
500
508static inline void _Chain_Initialize_empty(
509 Chain_Control *the_chain
510)
511{
512 Chain_Node *head;
513 Chain_Node *tail;
514
515 _Assert( the_chain != NULL );
516
517 head = _Chain_Head( the_chain );
518 tail = _Chain_Tail( the_chain );
519
520 head->next = tail;
521 head->previous = NULL;
522 tail->previous = head;
523}
524
531static inline void _Chain_Initialize_one(
532 Chain_Control *the_chain,
533 Chain_Node *the_node
534)
535{
536 Chain_Node *head;
537 Chain_Node *tail;
538
539 _Assert( _Chain_Is_node_off_chain( the_node ) );
540
541 head = _Chain_Head( the_chain );
542 tail = _Chain_Tail( the_chain );
543
544 the_node->next = tail;
545 the_node->previous = head;
546
547 head->next = the_node;
548 head->previous = NULL;
549 tail->previous = the_node;
550}
551
561static inline void _Chain_Extract_unprotected(
562 Chain_Node *the_node
563)
564{
565 Chain_Node *next;
566 Chain_Node *previous;
567
568 _Assert( !_Chain_Is_node_off_chain( the_node ) );
569
570 next = the_node->next;
571 previous = the_node->previous;
572 next->previous = previous;
573 previous->next = next;
574
575#if defined(RTEMS_DEBUG)
576 _Chain_Set_off_chain( the_node );
577#endif
578}
579
595static inline Chain_Node *_Chain_Get_first_unprotected(
596 Chain_Control *the_chain
597)
598{
599 Chain_Node *head;
600 Chain_Node *old_first;
601 Chain_Node *new_first;
602
603 _Assert( !_Chain_Is_empty( the_chain ) );
604
605 head = _Chain_Head( the_chain );
606 old_first = head->next;
607 new_first = old_first->next;
608
609 head->next = new_first;
610 new_first->previous = head;
611
612#if defined(RTEMS_DEBUG)
613 _Chain_Set_off_chain( old_first );
614#endif
615
616 return old_first;
617}
618
633static inline Chain_Node *_Chain_Get_unprotected(
634 Chain_Control *the_chain
635)
636{
637 if ( !_Chain_Is_empty(the_chain))
638 return _Chain_Get_first_unprotected(the_chain);
639 else
640 return NULL;
641}
642
656static inline void _Chain_Insert_unprotected(
657 Chain_Node *after_node,
658 Chain_Node *the_node
659)
660{
661 Chain_Node *before_node;
662
663 _Assert( _Chain_Is_node_off_chain( the_node ) );
664
665 the_node->previous = after_node;
666 before_node = after_node->next;
667 after_node->next = the_node;
668 the_node->next = before_node;
669 before_node->previous = the_node;
670}
671
683static inline void _Chain_Append_unprotected(
684 Chain_Control *the_chain,
685 Chain_Node *the_node
686)
687{
688 Chain_Node *tail;
689 Chain_Node *old_last;
690
691 _Assert( _Chain_Is_node_off_chain( the_node ) );
692
693 tail = _Chain_Tail( the_chain );
694 old_last = tail->previous;
695
696 the_node->next = tail;
697 tail->previous = the_node;
698 old_last->next = the_node;
699 the_node->previous = old_last;
700}
701
714static inline void _Chain_Append_if_is_off_chain_unprotected(
715 Chain_Control *the_chain,
716 Chain_Node *the_node
717)
718{
719 if ( _Chain_Is_node_off_chain( the_node ) ) {
720 _Chain_Append_unprotected( the_chain, the_node );
721 }
722}
723
735static inline void _Chain_Prepend_unprotected(
736 Chain_Control *the_chain,
737 Chain_Node *the_node
738)
739{
740 _Chain_Insert_unprotected(_Chain_Head(the_chain), the_node);
741}
742
757static inline bool _Chain_Append_with_empty_check_unprotected(
758 Chain_Control *the_chain,
759 Chain_Node *the_node
760)
761{
762 bool was_empty = _Chain_Is_empty( the_chain );
763
764 _Chain_Append_unprotected( the_chain, the_node );
765
766 return was_empty;
767}
768
783static inline bool _Chain_Prepend_with_empty_check_unprotected(
784 Chain_Control *the_chain,
785 Chain_Node *the_node
786)
787{
788 bool was_empty = _Chain_Is_empty( the_chain );
789
790 _Chain_Prepend_unprotected( the_chain, the_node );
791
792 return was_empty;
793}
794
813static inline bool _Chain_Get_with_empty_check_unprotected(
814 Chain_Control *the_chain,
815 Chain_Node **the_node
816)
817{
818 bool is_empty_now = true;
819 Chain_Node *head = _Chain_Head( the_chain );
820 Chain_Node *tail = _Chain_Tail( the_chain );
821 Chain_Node *old_first = head->next;
822
823 if ( old_first != tail ) {
824 Chain_Node *new_first = old_first->next;
825
826 head->next = new_first;
827 new_first->previous = head;
828
829 *the_node = old_first;
830
831 is_empty_now = new_first == tail;
832 } else
833 *the_node = NULL;
834
835 return is_empty_now;
836}
837
847typedef bool ( *Chain_Node_order )(
848 const void *key,
849 const Chain_Node *left,
850 const Chain_Node *right
851);
852
868static inline void _Chain_Insert_ordered_unprotected(
869 Chain_Control *the_chain,
870 Chain_Node *to_insert,
871 const void *key,
872 Chain_Node_order order
873)
874{
875 const Chain_Node *tail = _Chain_Immutable_tail( the_chain );
876 Chain_Node *previous = _Chain_Head( the_chain );
877 Chain_Node *next = _Chain_First( the_chain );
878
879 while ( next != tail && !( *order )( key, to_insert, next ) ) {
880 previous = next;
881 next = _Chain_Next( next );
882 }
883
884 _Chain_Insert_unprotected( previous, to_insert );
885}
886
890typedef enum {
895
901
908typedef struct {
915
922
933
940typedef struct {
941 Chain_Control Iterators;
943
949#define CHAIN_ITERATOR_REGISTRY_INITIALIZER( name ) \
950 { CHAIN_INITIALIZER_EMPTY( name.Iterators ) }
951
957static inline void _Chain_Iterator_registry_initialize(
958 Chain_Iterator_registry *the_registry
959)
960{
961 _Chain_Initialize_empty( &the_registry->Iterators );
962}
963
976static inline void _Chain_Iterator_registry_update(
977 Chain_Iterator_registry *the_registry,
978 Chain_Node *the_node_to_extract
979)
980{
981 Chain_Node *iter_node;
982 Chain_Node *iter_tail;
983
984 iter_node = _Chain_Head( &the_registry->Iterators );
985 iter_tail = _Chain_Tail( &the_registry->Iterators );
986
987 while ( ( iter_node = _Chain_Next( iter_node ) ) != iter_tail ) {
988 Chain_Iterator *iter;
989
990 iter = (Chain_Iterator *) iter_node;
991
992 if ( iter->position == the_node_to_extract ) {
993 if ( iter->direction == CHAIN_ITERATOR_FORWARD ) {
994 iter->position = _Chain_Previous( the_node_to_extract );
995 } else {
996 iter->position = _Chain_Next( the_node_to_extract );
997 }
998 }
999 }
1000}
1001
1063static inline void _Chain_Iterator_initialize(
1064 Chain_Control *the_chain,
1065 Chain_Iterator_registry *the_registry,
1066 Chain_Iterator *the_iterator,
1067 Chain_Iterator_direction direction
1068)
1069{
1070 _Chain_Initialize_node( &the_iterator->Registry_node );
1071 _Chain_Append_unprotected(
1072 &the_registry->Iterators,
1073 &the_iterator->Registry_node
1074 );
1075
1076 the_iterator->direction = direction;
1077
1078 if ( direction == CHAIN_ITERATOR_FORWARD ) {
1079 the_iterator->position = _Chain_Head( the_chain );
1080 } else {
1081 the_iterator->position = _Chain_Tail( the_chain );
1082 }
1083}
1084
1095static inline Chain_Node *_Chain_Iterator_next(
1096 const Chain_Iterator *the_iterator
1097)
1098{
1099 if ( the_iterator->direction == CHAIN_ITERATOR_FORWARD ) {
1100 return _Chain_Next( the_iterator->position );
1101 } else {
1102 return _Chain_Previous( the_iterator->position );
1103 }
1104}
1105
1112static inline void _Chain_Iterator_set_position(
1113 Chain_Iterator *the_iterator,
1114 Chain_Node *the_node
1115)
1116{
1117 the_iterator->position = the_node;
1118}
1119
1127static inline void _Chain_Iterator_destroy(
1128 Chain_Iterator *the_iterator
1129)
1130{
1131 _Chain_Extract_unprotected( &the_iterator->Registry_node );
1132}
1133
1136#ifdef __cplusplus
1137}
1138#endif
1139
1140#endif
1141/* 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:847
Chain_Iterator_direction
The chain iterator direction.
Definition: chainimpl.h:890
@ CHAIN_ITERATOR_BACKWARD
Iteration from tail to head.
Definition: chainimpl.h:899
@ CHAIN_ITERATOR_FORWARD
Iteration from head to tail.
Definition: chainimpl.h:894
#define NULL
Requests a GPIO pin group configuration.
Definition: xil_types.h:54
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:940
A chain iterator which is updated during node extraction if it is properly registered.
Definition: chainimpl.h:908
Chain_Node * position
The current position of this iterator.
Definition: chainimpl.h:931
Chain_Node Registry_node
Node for registration.
Definition: chainimpl.h:914
Chain_Iterator_direction direction
The direction of this iterator.
Definition: chainimpl.h:921
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