source: rtems-docs/c_user/chains.rst @ 01a36ee

4.115
Last change on this file since 01a36ee was 489740f, checked in by Chris Johns <chrisj@…>, on 05/20/16 at 02:47:09

Set SPDX License Identifier in each source file.

  • Property mode set to 100644
File size: 18.4 KB
Line 
1.. comment SPDX-License-Identifier: CC-BY-SA-4.0
2
3.. COMMENT: Copyright 2014 Gedare Bloom.
4.. COMMENT: All rights reserved.
5
6Chains
7######
8
9.. index:: chains
10
11Introduction
12============
13
14The Chains API is an interface to the Super Core (score) chain
15implementation. The Super Core uses chains for all list type functions. This
16includes wait queues and task queues. The Chains API provided by RTEMS is:
17
18- ``rtems_chain_node`` - Chain node used in user objects
19
20- ``rtems_chain_control`` - Chain control node
21
22- rtems_chain_initialize_ - initialize the chain with nodes
23
24- rtems_chain_initialize_empty_ - initialize the chain as empty
25
26- rtems_chain_is_null_node_ - Is the node NULL ?
27
28- rtems_chain_head_ - Return the chain's head
29
30- rtems_chain_tail_ - Return the chain's tail
31
32- rtems_chain_are_nodes_equal_ - Are the node's equal ?
33
34- rtems_chain_is_empty_ - Is the chain empty ?
35
36- rtems_chain_is_first_ - Is the Node the first in the chain ?
37
38- rtems_chain_is_last_ - Is the Node the last in the chain ?
39
40- rtems_chain_has_only_one_node_ - Does the node have one node ?
41
42- rtems_chain_node_count_unprotected_ - Returns the node count of the chain (unprotected)
43
44- rtems_chain_is_head_ - Is the node the head ?
45
46- rtems_chain_is_tail_ - Is the node the tail ?
47
48- rtems_chain_extract_ - Extract the node from the chain
49
50- rtems_chain_extract_unprotected_ - Extract the node from the chain (unprotected)
51
52- rtems_chain_get_ - Return the first node on the chain
53
54- rtems_chain_get_unprotected_ - Return the first node on the chain (unprotected)
55
56- rtems_chain_insert_ - Insert the node into the chain
57
58- rtems_chain_insert_unprotected_ - Insert the node into the chain (unprotected)
59
60- rtems_chain_append_ - Append the node to chain
61
62- rtems_chain_append_unprotected_ - Append the node to chain (unprotected)
63
64- rtems_chain_prepend_ - Prepend the node to the end of the chain
65
66- rtems_chain_prepend_unprotected_ - Prepend the node to chain (unprotected)
67
68Background
69==========
70
71The Chains API maps to the Super Core Chains API. Chains are implemented as a
72double linked list of nodes anchored to a control node. The list starts at the
73control node and is terminated at the control node. A node has previous and
74next pointers. Being a double linked list nodes can be inserted and removed
75without the need to travse the chain.
76
77Chains have a small memory footprint and can be used in interrupt service
78routines and are thread safe in a multi-threaded environment. The directives
79list which operations disable interrupts.
80
81Chains are very useful in Board Support packages and applications.
82
83Nodes
84-----
85
86A chain is made up from nodes that orginate from a chain control object. A node
87is of type ``rtems_chain_node``. The node is designed to be part of a user data
88structure and a cast is used to move from the node address to the user data
89structure address. For example:
90
91.. code-block:: c
92
93    typedef struct foo
94    {
95        rtems_chain_node node;
96        int              bar;
97    } foo;
98
99creates a type ``foo`` that can be placed on a chain. To get the foo structure
100from the list you perform the following:
101
102.. code-block:: c
103
104    foo* get_foo(rtems_chain_control* control)
105    {
106        return (foo*) rtems_chain_get(control);
107    }
108
109The node is placed at the start of the user's structure to allow the node
110address on the chain to be easly cast to the user's structure address.
111
112Controls
113--------
114
115A chain is anchored with a control object. Chain control provide the user with
116access to the nodes on the chain. The control is head of the node.
117
118.. code-block:: c
119
120    [Control]
121    first ------------------------>
122    permanent_null <--------------- [NODE]
123    last ------------------------->
124
125The implementation does not require special checks for manipulating the first
126and last nodes on the chain. To accomplish this the ``rtems_chain_control``
127structure is treated as two overlapping ``rtems_chain_node`` structures.  The
128permanent head of the chain overlays a node structure on the first and
129``permanent_null`` fields.  The ``permanent_tail`` of the chain overlays a node
130structure on the ``permanent_null`` and ``last`` elements of the structure.
131
132Operations
133==========
134
135Multi-threading
136---------------
137
138Chains are designed to be used in a multi-threading environment. The directives
139list which operations mask interrupts. Chains supports tasks and interrupt
140service routines appending and extracting nodes with out the need for extra
141locks. Chains how-ever cannot insure the integrity of a chain for all
142operations. This is the responsibility of the user. For example an interrupt
143service routine extracting nodes while a task is iterating over the chain can
144have unpredictable results.
145
146Creating a Chain
147----------------
148
149To create a chain you need to declare a chain control then add nodes
150to the control. Consider a user structure and chain control:
151
152.. code-block:: c
153
154    typedef struct foo
155    {
156        rtems_chain_node node;
157        uint8_t char*    data;
158    } foo;
159    rtems_chain_control chain;
160
161Add nodes with the following code:
162
163.. code-block:: c
164
165    rtems_chain_initialize_empty (&chain);
166
167    for (i = 0; i < count; i++)
168    {
169        foo* bar = malloc (sizeof (foo));
170        if (!bar)
171            return -1;
172        bar->data = malloc (size);
173        rtems_chain_append (&chain, &bar->node);
174    }
175
176The chain is initialized and the nodes allocated and appended to the
177chain. This is an example of a pool of buffers.
178
179Iterating a Chain
180-----------------
181.. index:: chain iterate
182
183Iterating a chain is a common function. The example shows how to iterate the
184buffer pool chain created in the last section to find buffers starting with a
185specific string. If the buffer is located it is extracted from the chain and
186placed on another chain:
187
188.. code-block:: c
189
190    void foobar (const char*          match,
191                 rtems_chain_control* chain,
192                 rtems_chain_control* out)
193    {
194        rtems_chain_node* node;
195        foo*              bar;
196
197        rtems_chain_initialize_empty (out);
198
199        node = chain->first;
200        while (!rtems_chain_is_tail (chain, node))
201        {
202            bar = (foo*) node;
203            rtems_chain_node* next_node = node->next;
204            if (strcmp (match, bar->data) == 0)
205            {
206                rtems_chain_extract (node);
207                rtems_chain_append (out, node);
208            }
209            node = next_node;
210        }
211    }
212
213Directives
214==========
215
216The section details the Chains directives.
217
218.. COMMENT: Initialize this Chain With Nodes
219
220.. _rtems_chain_initialize:
221
222Initialize Chain With Nodes
223---------------------------
224.. index:: chain initialize
225
226**CALLING SEQUENCE:**
227
228.. index:: rtems_chain_initialize
229
230.. code-block:: c
231
232    void rtems_chain_initialize(
233        rtems_chain_control *the_chain,
234        void                *starting_address,
235        size_t               number_nodes,
236        size_t               node_size
237    )
238
239**RETURNS**
240
241Returns nothing.
242
243**DESCRIPTION:**
244
245This function take in a pointer to a chain control and initializes it to
246contain a set of chain nodes.  The chain will contain ``number_nodes`` chain
247nodes from the memory pointed to by ``start_address``.  Each node is assumed to
248be ``node_size`` bytes.
249
250**NOTES:**
251
252This call will discard any nodes on the chain.
253
254This call does NOT inititialize any user data on each node.
255
256.. COMMENT: Initialize this Chain as Empty
257
258.. _rtems_chain_initialize_empty:
259
260Initialize Empty
261----------------
262.. index:: chain initialize empty
263
264**CALLING SEQUENCE:**
265
266.. index:: rtems_chain_initialize_empty
267
268.. code-block:: c
269
270    void rtems_chain_initialize_empty(
271        rtems_chain_control *the_chain
272    );
273
274**RETURNS**
275
276Returns nothing.
277
278**DESCRIPTION:**
279
280This function take in a pointer to a chain control and initializes it to empty.
281
282**NOTES:**
283
284This call will discard any nodes on the chain.
285
286.. _rtems_chain_is_null_node:
287
288Is Null Node ?
289--------------
290.. index:: chain is node null
291
292**CALLING SEQUENCE:**
293
294.. index:: rtems_chain_is_null_node
295
296.. code-block:: c
297
298    bool rtems_chain_is_null_node(
299        const rtems_chain_node *the_node
300    );
301
302**RETURNS**
303
304Returns ``true`` is the node point is NULL and ``false`` if the node is not
305NULL.
306
307**DESCRIPTION:**
308
309Tests the node to see if it is a NULL returning ``true`` if a null.
310
311.. _rtems_chain_head:
312
313Head
314----
315.. index:: chain get head
316
317**CALLING SEQUENCE:**
318
319.. index:: rtems_chain_head
320
321.. code-block:: c
322
323    rtems_chain_node *rtems_chain_head(
324        rtems_chain_control *the_chain
325    )
326
327**RETURNS**
328
329Returns the permanent head node of the chain.
330
331**DESCRIPTION:**
332
333This function returns a pointer to the first node on the chain.
334
335.. _rtems_chain_tail:
336
337Tail
338----
339.. index:: chain get tail
340
341**CALLING SEQUENCE:**
342
343.. index:: rtems_chain_tail
344
345.. code-block:: c
346
347    rtems_chain_node *rtems_chain_tail(
348        rtems_chain_control *the_chain
349    );
350
351**RETURNS**
352
353Returns the permanent tail node of the chain.
354
355**DESCRIPTION:**
356
357This function returns a pointer to the last node on the chain.
358
359.. _rtems_chain_are_nodes_equal:
360
361Are Two Nodes Equal ?
362---------------------
363.. index:: chare are nodes equal
364
365**CALLING SEQUENCE:**
366
367.. index:: rtems_chain_are_nodes_equal
368
369.. code-block:: c
370
371    bool rtems_chain_are_nodes_equal(
372        const rtems_chain_node *left,
373        const rtems_chain_node *right
374    );
375
376**RETURNS**
377
378This function returns ``true`` if the left node and the right node are equal,
379and ``false`` otherwise.
380
381**DESCRIPTION:**
382
383This function returns ``true`` if the left node and the right node are equal,
384and ``false`` otherwise.
385
386.. _rtems_chain_is_empty:
387
388Is the Chain Empty
389------------------
390.. index:: chain is chain empty
391
392**CALLING SEQUENCE:**
393
394.. index:: rtems_chain_is_empty
395
396.. code-block:: c
397
398    bool rtems_chain_is_empty(
399        rtems_chain_control *the_chain
400    );
401
402**RETURNS**
403
404This function returns ``true`` if there a no nodes on the chain and ``false``
405otherwise.
406
407**DESCRIPTION:**
408
409This function returns ``true`` if there a no nodes on the chain and ``false``
410otherwise.
411
412.. _rtems_chain_is_first:
413
414Is this the First Node on the Chain ?
415-------------------------------------
416.. index:: chain is node the first
417
418**CALLING SEQUENCE:**
419
420.. index:: rtems_chain_is_first
421
422.. code-block:: c
423
424    bool rtems_chain_is_first(
425        const rtems_chain_node *the_node
426    );
427
428**RETURNS**
429
430This function returns ``true`` if the node is the first node on a chain and
431``false`` otherwise.
432
433**DESCRIPTION:**
434
435This function returns ``true`` if the node is the first node on a chain and
436``false`` otherwise.
437
438.. _rtems_chain_is_last:
439
440Is this the Last Node on the Chain ?
441------------------------------------
442.. index:: chain is node the last
443
444**CALLING SEQUENCE:**
445
446.. index:: rtems_chain_is_last
447
448.. code-block:: c
449
450    bool rtems_chain_is_last(
451        const rtems_chain_node *the_node
452    );
453
454**RETURNS**
455
456This function returns ``true`` if the node is the last node on a chain and
457``false`` otherwise.
458
459**DESCRIPTION:**
460
461This function returns ``true`` if the node is the last node on a chain and
462``false`` otherwise.
463
464.. _rtems_chain_has_only_one_node:
465
466Does this Chain have only One Node ?
467------------------------------------
468.. index:: chain only one node
469
470**CALLING SEQUENCE:**
471
472.. index:: rtems_chain_has_only_one_node
473
474.. code-block:: c
475
476    bool rtems_chain_has_only_one_node(
477        const rtems_chain_control *the_chain
478    );
479
480**RETURNS**
481
482This function returns ``true`` if there is only one node on the chain and
483``false`` otherwise.
484
485**DESCRIPTION:**
486
487This function returns ``true`` if there is only one node on the chain and
488``false`` otherwise.
489
490.. _rtems_chain_node_count_unprotected:
491
492Returns the node count of the chain (unprotected)
493-------------------------------------------------
494.. index:: chain only one node
495
496**CALLING SEQUENCE:**
497
498.. index:: rtems_chain_node_count_unprotected
499
500.. code-block:: c
501
502    size_t rtems_chain_node_count_unprotected(
503        const rtems_chain_control *the_chain
504    );
505
506**RETURNS**
507
508This function returns the node count of the chain.
509
510**DESCRIPTION:**
511
512This function returns the node count of the chain.
513
514.. _rtems_chain_is_head:
515
516Is this Node the Chain Head ?
517-----------------------------
518.. index:: chain is node the head
519
520**CALLING SEQUENCE:**
521
522.. index:: rtems_chain_is_head
523
524.. code-block:: c
525
526    bool rtems_chain_is_head(
527        rtems_chain_control    *the_chain,
528        rtems_const chain_node *the_node
529    );
530
531**RETURNS**
532
533This function returns ``true`` if the node is the head of the chain and
534``false`` otherwise.
535
536**DESCRIPTION:**
537
538This function returns ``true`` if the node is the head of the chain and
539``false`` otherwise.
540
541.. _rtems_chain_is_tail:
542
543Is this Node the Chain Tail ?
544-----------------------------
545.. index:: chain is node the tail
546
547**CALLING SEQUENCE:**
548
549.. index:: rtems_chain_is_tail
550
551.. code-block:: c
552
553    bool rtems_chain_is_tail(
554        rtems_chain_control    *the_chain,
555        const rtems_chain_node *the_node
556    )
557
558**RETURNS**
559
560This function returns ``true`` if the node is the tail of the chain and
561``false`` otherwise.
562
563**DESCRIPTION:**
564
565This function returns ``true`` if the node is the tail of the chain and
566``false`` otherwise.
567
568.. _rtems_chain_extract:
569
570Extract a Node
571--------------
572.. index:: chain extract a node
573
574**CALLING SEQUENCE:**
575
576.. index:: rtems_chain_extract
577
578.. code-block:: c
579
580    void rtems_chain_extract(
581        rtems_chain_node *the_node
582    );
583
584**RETURNS**
585
586Returns nothing.
587
588**DESCRIPTION:**
589
590This routine extracts the node from the chain on which it resides.
591
592**NOTES:**
593
594Interrupts are disabled while extracting the node to ensure the atomicity of
595the operation.
596
597Use rtems_chain_extract_unprotected_ to avoid disabling of interrupts.
598
599.. _rtems_chain_extract_unprotected:
600
601Extract a Node (unprotected)
602----------------------------
603.. index:: chain extract a node unprotected
604
605**CALLING SEQUENCE:**
606
607.. index:: rtems_chain_extract_unprotected
608
609.. code-block:: c
610
611    void rtems_chain_extract_unprotected(
612        rtems_chain_node *the_node
613    );
614
615**RETURNS**
616
617Returns nothing.
618
619**DESCRIPTION:**
620
621This routine extracts the node from the chain on which it resides.
622
623**NOTES:**
624
625The function does nothing to ensure the atomicity of the operation.
626
627.. _rtems_chain_get:
628
629Get the First Node
630------------------
631.. index:: chain get first node
632
633**CALLING SEQUENCE:**
634
635.. index:: rtems_chain_get
636
637.. code-block:: c
638
639    rtems_chain_node *rtems_chain_get(
640        rtems_chain_control *the_chain
641    );
642
643**RETURNS**
644
645Returns a pointer a node. If a node was removed, then a pointer to that node is
646returned. If the chain was empty, then ``NULL`` is returned.
647
648**DESCRIPTION:**
649
650This function removes the first node from the chain and returns a pointer to
651that node.  If the chain is empty, then ``NULL`` is returned.
652
653**NOTES:**
654
655Interrupts are disabled while obtaining the node to ensure the atomicity of the
656operation.
657
658Use ``rtems_chain_get_unprotected()`` to avoid disabling of interrupts.
659
660.. _rtems_chain_get_unprotected:
661
662Get the First Node (unprotected)
663--------------------------------
664.. index:: chain get first node
665
666**CALLING SEQUENCE:**
667
668.. index:: rtems_chain_get_unprotected
669
670.. code-block:: c
671
672    rtems_chain_node *rtems_chain_get_unprotected(
673        rtems_chain_control *the_chain
674    );
675
676**RETURNS:**
677
678A pointer to the former first node is returned.
679
680**DESCRIPTION:**
681
682Removes the first node from the chain and returns a pointer to it.  In case the
683chain was empty, then the results are unpredictable.
684
685**NOTES:**
686
687The function does nothing to ensure the atomicity of the operation.
688
689.. _rtems_chain_insert:
690
691Insert a Node
692-------------
693.. index:: chain insert a node
694
695**CALLING SEQUENCE:**
696
697.. index:: rtems_chain_insert
698
699.. code-block:: c
700
701    void rtems_chain_insert(
702        rtems_chain_node *after_node,
703        rtems_chain_node *the_node
704    );
705
706**RETURNS**
707
708Returns nothing.
709
710**DESCRIPTION:**
711
712This routine inserts a node on a chain immediately following the specified
713node.
714
715**NOTES:**
716
717Interrupts are disabled during the insert to ensure the atomicity of the
718operation.
719
720Use rtems_chain_insert_unprotected_ to avoid disabling of interrupts.
721
722.. _rtems_chain_insert_unprotected:
723
724Insert a Node (unprotected)
725---------------------------
726.. index:: chain insert a node unprotected
727
728**CALLING SEQUENCE:**
729
730.. index:: rtems_chain_insert_unprotected
731
732.. code-block:: c
733
734    void rtems_chain_insert_unprotected(
735        rtems_chain_node *after_node,
736        rtems_chain_node *the_node
737    );
738
739**RETURNS**
740
741Returns nothing.
742
743**DESCRIPTION:**
744
745This routine inserts a node on a chain immediately following the specified
746node.
747
748**NOTES:**
749
750The function does nothing to ensure the atomicity of the operation.
751
752.. _rtems_chain_append:
753
754Append a Node
755-------------
756.. index:: chain append a node
757
758**CALLING SEQUENCE:**
759
760.. index:: rtems_chain_append
761
762.. code-block:: c
763
764    void rtems_chain_append(
765        rtems_chain_control *the_chain,
766        rtems_chain_node    *the_node
767    );
768
769**RETURNS**
770
771Returns nothing.
772
773**DESCRIPTION:**
774
775This routine appends a node to the end of a chain.
776
777**NOTES:**
778
779Interrupts are disabled during the append to ensure the atomicity of the
780operation.
781
782Use rtems_chain_append_unprotected_ to avoid disabling of interrupts.
783
784.. _rtems_chain_append_unprotected:
785
786Append a Node (unprotected)
787---------------------------
788.. index:: chain append a node unprotected
789
790**CALLING SEQUENCE:**
791
792.. index:: rtems_chain_append_unprotected
793
794.. code-block:: c
795
796    void rtems_chain_append_unprotected(
797        rtems_chain_control *the_chain,
798        rtems_chain_node    *the_node
799    );
800
801**RETURNS**
802
803Returns nothing.
804
805**DESCRIPTION:**
806
807This routine appends a node to the end of a chain.
808
809**NOTES:**
810
811The function does nothing to ensure the atomicity of the operation.
812
813.. _rtems_chain_prepend:
814
815Prepend a Node
816--------------
817.. index:: prepend node
818
819**CALLING SEQUENCE:**
820
821.. index:: rtems_chain_prepend
822
823.. code-block:: c
824
825    void rtems_chain_prepend(
826        rtems_chain_control *the_chain,
827        rtems_chain_node    *the_node
828    );
829
830**RETURNS**
831
832Returns nothing.
833
834**DESCRIPTION:**
835
836This routine prepends a node to the front of the chain.
837
838**NOTES:**
839
840Interrupts are disabled during the prepend to ensure the atomicity of the
841operation.
842
843Use rtems_chain_prepend_unprotected_ to avoid disabling of
844interrupts.
845
846.. _rtems_chain_prepend_unprotected:
847
848Prepend a Node (unprotected)
849----------------------------
850.. index:: prepend node unprotected
851
852**CALLING SEQUENCE:**
853
854.. index:: rtems_chain_prepend_unprotected
855
856.. code-block:: c
857
858    void rtems_chain_prepend_unprotected(
859        rtems_chain_control *the_chain,
860        rtems_chain_node    *the_node
861    );
862
863**RETURNS**
864
865Returns nothing.
866
867**DESCRIPTION:**
868
869This routine prepends a node to the front of the chain.
870
871**NOTES:**
872
873The function does nothing to ensure the atomicity of the operation.
Note: See TracBrowser for help on using the repository browser.