summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2017-04-04 12:00:28 +0200
committerCorinna Vinschen <corinna@vinschen.de>2017-04-04 12:16:05 +0200
commit9998bd4b7c4596e47d8e0fbc6f1f370d096a6618 (patch)
tree68c65e9a1100a2e0498fb788c12922b9294344a8
parent218c5e7d7264f1ed532d64d1932104fd8864b962 (diff)
downloadcygnal-9998bd4b7c4596e47d8e0fbc6f1f370d096a6618.tar.gz
cygnal-9998bd4b7c4596e47d8e0fbc6f1f370d096a6618.tar.bz2
cygnal-9998bd4b7c4596e47d8e0fbc6f1f370d096a6618.zip
Add two new macros, SLIST_CONCAT and LIST_CONCAT
Add two new macros, SLIST_CONCAT and LIST_CONCAT. Note in both the queue.h header file and in the queue.3 manual page that they are O(n) so should be used only in low-usage paths with short lists (otherwise an STAILQ or TAILQ should be used). Reviewed by: kib
-rw-r--r--newlib/libc/include/sys/queue.h38
1 files changed, 36 insertions, 2 deletions
diff --git a/newlib/libc/include/sys/queue.h b/newlib/libc/include/sys/queue.h
index d6c821f7d..46bb69f29 100644
--- a/newlib/libc/include/sys/queue.h
+++ b/newlib/libc/include/sys/queue.h
@@ -76,6 +76,10 @@
*
* For details on the use of these macros, see the queue(3) manual page.
*
+ * Below is a summary of implemented functions where:
+ * + means the macro is available
+ * - means the macro is not available
+ * s means the macro is available but is slow (runs in O(n) time)
*
* SLIST LIST STAILQ TAILQ
* _HEAD + + + +
@@ -101,10 +105,10 @@
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
* _INSERT_TAIL - - + +
- * _CONCAT - - + +
+ * _CONCAT s s + +
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
- * _REMOVE + + + +
+ * _REMOVE s + s +
* _SWAP + + + +
*
*/
@@ -183,6 +187,19 @@ struct { \
/*
* Singly-linked List functions.
*/
+#define SLIST_CONCAT(head1, head2, type, field) do { \
+ QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \
+ if (curelm == NULL) { \
+ if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \
+ SLIST_INIT(head2); \
+ } else if (SLIST_FIRST(head2) != NULL) { \
+ while (SLIST_NEXT(curelm, field) != NULL) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \
+ SLIST_INIT(head2); \
+ } \
+} while (0)
+
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
@@ -452,6 +469,23 @@ struct { \
#define QMD_LIST_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
+#define LIST_CONCAT(head1, head2, type, field) do { \
+ QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \
+ if (curelm == NULL) { \
+ if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \
+ LIST_FIRST(head2)->field.le_prev = \
+ &LIST_FIRST((head1)); \
+ LIST_INIT(head2); \
+ } \
+ } else if (LIST_FIRST(head2) != NULL) { \
+ while (LIST_NEXT(curelm, field) != NULL) \
+ curelm = LIST_NEXT(curelm, field); \
+ LIST_NEXT(curelm, field) = LIST_FIRST(head2); \
+ LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \
+ LIST_INIT(head2); \
+ } \
+} while (0)
+
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)