source: rtems/cpukit/score/include/rtems/score/chainimpl.h @ 6e93dc4a

4.11
Last change on this file since 6e93dc4a was 6e93dc4a, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 22, 2013 at 8:49:19 AM

score: Create chain implementation header

Move implementation specific parts of chain.h and chain.inl into new
header file chainimpl.h. The chain.h contains now only the application
visible API.

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