summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2021-03-02 22:30:01 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2021-03-02 22:30:01 (GMT)
commitae24b82f778579795395510aee52293f41b95aad (patch)
treea27af16a2db96eeff18401a163aa8c45f4eeb879 /src
parent69b2061d68aa85c8925c15a334fc5c3fb12e377f (diff)
parentdb95737047fbbf967d928bf9a693d470884f4890 (diff)
downloadhdf5-ae24b82f778579795395510aee52293f41b95aad.zip
hdf5-ae24b82f778579795395510aee52293f41b95aad.tar.gz
hdf5-ae24b82f778579795395510aee52293f41b95aad.tar.bz2
Brings MacOS fixes from main feature branch
Diffstat (limited to 'src')
-rw-r--r--src/H5FD.c40
-rw-r--r--src/H5FDpublic.h16
-rw-r--r--src/H5FDvfd_swmr.h7
-rw-r--r--src/H5FDvfd_swmr_private.h6
-rw-r--r--src/H5Fpkg.h3
-rw-r--r--src/H5private.h7
-rw-r--r--src/H5queue.h369
7 files changed, 150 insertions, 298 deletions
diff --git a/src/H5FD.c b/src/H5FD.c
index 602b198..f34a2ec 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -54,6 +54,11 @@
/* Package Typedefs */
/********************/
+/* H5FD wrapper for VFD SWMR. Allows use as a BSD TAILQ element. */
+typedef struct H5FD_wrap_t {
+ TAILQ_ENTRY(H5FD_wrap_t) link; /* Linkage for list of all VFDs. */
+ H5FD_t *file; /* Pointer to wrapped VFD struct */
+} H5FD_wrap_t;
/********************/
/* Local Prototypes */
@@ -92,7 +97,7 @@ hbool_t H5_PKG_INIT_VAR = FALSE;
*/
static unsigned long H5FD_file_serial_no_g;
-static TAILQ_HEAD(_all_vfds, H5FD_t) all_vfds = TAILQ_HEAD_INITIALIZER(all_vfds);
+static TAILQ_HEAD(_all_vfds, H5FD_wrap_t) all_vfds = TAILQ_HEAD_INITIALIZER(all_vfds);
/* File driver ID class */
static const H5I_class_t H5I_VFL_CLS[1] = {{
@@ -726,18 +731,19 @@ H5FD_dedup(H5FD_t *self, H5FD_t *other, hid_t fapl)
H5FD_t *
H5FD_deduplicate(H5FD_t *file, hid_t fapl)
{
- H5FD_t *deduped = file, *item;
+ H5FD_t *deduped = file;
+ H5FD_wrap_t *item;
TAILQ_FOREACH(item, &all_vfds, link) {
/* skip "self" */
- if (item == file)
+ if (item->file == file)
continue;
/* skip files with exclusive owners, for now */
- if (item->exc_owner != NULL)
+ if (item->file->exc_owner != NULL)
continue;
- if ((deduped = H5FD_dedup(item, file, fapl)) != file)
+ if ((deduped = H5FD_dedup(item->file, file, fapl)) != file)
goto finish;
}
@@ -746,10 +752,10 @@ H5FD_deduplicate(H5FD_t *file, hid_t fapl)
* return NULL to indicate the conflict.
*/
TAILQ_FOREACH(item, &all_vfds, link) {
- if (item == file || item->exc_owner == NULL)
+ if (item->file == file || item->file->exc_owner == NULL)
continue;
- if (H5FDcmp(file, item) == 0) {
+ if (H5FDcmp(file, item->file) == 0) {
deduped = NULL;
break;
}
@@ -784,6 +790,7 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
H5P_genplist_t *plist; /* Property list pointer */
unsigned long driver_flags = 0; /* File-inspecific driver feature flags */
H5FD_file_image_info_t file_image_info; /* Initial file image */
+ H5FD_wrap_t *swmr_wrapper = NULL; /* H5FD wrapper for SWMR queue */
H5FD_t *ret_value = NULL; /* Return value */
FUNC_ENTER_NOAPI(NULL)
@@ -862,7 +869,11 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
/* (This will be changed later, when the superblock is located) */
file->base_addr = 0;
- TAILQ_INSERT_TAIL(&all_vfds, file, link);
+ /* Create and insert a SWMR wrapper for the file */
+ if(NULL == (swmr_wrapper = H5MM_calloc(sizeof(H5FD_wrap_t))))
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, NULL, "unable to allocate file wrap struct")
+ swmr_wrapper->file = file;
+ TAILQ_INSERT_TAIL(&all_vfds, swmr_wrapper, link);
/* Set return value */
ret_value = file;
@@ -923,7 +934,8 @@ herr_t
H5FD_close(H5FD_t *file)
{
const H5FD_class_t *driver;
- H5FD_t *item;
+ H5FD_wrap_t *item;
+ H5FD_wrap_t *delete_me = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(FAIL)
@@ -938,10 +950,14 @@ H5FD_close(H5FD_t *file)
HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
TAILQ_FOREACH(item, &all_vfds, link) {
- if (item->exc_owner == file)
- item->exc_owner = NULL;
+ if (item->file->exc_owner == file)
+ item->file->exc_owner = NULL;
+ if (item->file == file)
+ delete_me = item;
}
- TAILQ_REMOVE(&all_vfds, file, link);
+ HDassert(delete_me);
+ TAILQ_REMOVE(&all_vfds, delete_me, link);
+ H5MM_xfree(delete_me);
/* Dispatch to the driver for actual close. If the driver fails to
* close the file then the file will be in an unusable state.
diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h
index a921c29..520668b 100644
--- a/src/H5FDpublic.h
+++ b/src/H5FDpublic.h
@@ -18,7 +18,6 @@
#ifndef _H5FDpublic_H
#define _H5FDpublic_H
-#include "H5queue.h"
#include "H5public.h"
#include "H5Fpublic.h" /*for H5F_close_degree_t */
@@ -319,19 +318,18 @@ typedef struct H5FD_free_t {
* are declared here and the driver appends private fields in memory.
*/
struct H5FD_t {
- hid_t driver_id; /*driver ID for this file */
- const H5FD_class_t *cls; /*constant class info */
-
- TAILQ_ENTRY(H5FD_t) link; /* Linkage for list of all VFs. */
- H5FD_t *exc_owner; /* Pointer to an exclusive owner
- * or NULL if none.
- */
- unsigned long fileno; /* File 'serial' number */
+ hid_t driver_id; /* Driver ID for this file */
+ const H5FD_class_t *cls; /* Constant class info */
+ unsigned long fileno; /* File 'serial' number */
unsigned access_flags; /* File access flags (from create or open) */
unsigned long feature_flags; /* VFL Driver feature Flags */
haddr_t maxaddr; /* For this file, overrides class */
haddr_t base_addr; /* Base address for HDF5 data w/in file */
+ H5FD_t *exc_owner; /* Pointer to an exclusive owner
+ * or NULL if none.
+ */
+
/* Space allocation management fields */
hsize_t threshold; /* Threshold for alignment */
hsize_t alignment; /* Allocation alignment */
diff --git a/src/H5FDvfd_swmr.h b/src/H5FDvfd_swmr.h
index 86e9d0f..7d3b966 100644
--- a/src/H5FDvfd_swmr.h
+++ b/src/H5FDvfd_swmr.h
@@ -14,8 +14,8 @@
/*
* The public header file for the VFD SWMR driver.
*/
-#ifndef H5FDswmr_H
-#define H5FDswmr_H
+#ifndef H5FDvfd_swmr_H
+#define H5FDvfd_swmr_H
#include "H5api_adpt.h" /* H5_DLL */
#include "H5public.h" /* uint64_t *ahem* */
@@ -34,5 +34,4 @@ H5_DLL herr_t H5Pset_fapl_vfd_swmr(hid_t fapl_id);
}
#endif
-#endif
-
+#endif /* H5FDvfd_swmr_H */
diff --git a/src/H5FDvfd_swmr_private.h b/src/H5FDvfd_swmr_private.h
index 551adaa..e2270b9 100644
--- a/src/H5FDvfd_swmr_private.h
+++ b/src/H5FDvfd_swmr_private.h
@@ -9,8 +9,8 @@
* help@hdfgroup.org.
*/
-#ifndef _H5FDvfd_swmr_private_H
-#define _H5FDvfd_swmr_private_H
+#ifndef H5FDvfd_swmr_private_H
+#define H5FDvfd_swmr_private_H
#include "H5queue.h" /* for TAILQ_* */
@@ -84,4 +84,4 @@ H5_DLL herr_t H5F_vfd_swmr_insert_entry_eot(struct H5F_t *f);
H5_DLL void H5F_vfd_swmr_update_entry_eot(eot_queue_entry_t *);
H5_DLL herr_t H5F_dump_eot_queue(void);
-#endif /* _H5FDvfd_swmr_private_H */
+#endif /* H5FDvfd_swmr_private_H */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 71d0ce4..260a25c 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -26,9 +26,6 @@
#ifndef _H5Fpkg_H
#define _H5Fpkg_H
-/* BSD queue macros */
-#include "H5queue.h"
-
/* Get package's private header */
#include "H5Fprivate.h"
diff --git a/src/H5private.h b/src/H5private.h
index 6479032..66763b2 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -171,6 +171,13 @@
#include <dirent.h>
#endif
+/* BSD-style queues
+ *
+ * We use a private copy of netBSD's queues instead of including sys/queue.h
+ * due to irreconcilable differences between different queue implementations.
+ */
+#include "H5queue.h"
+
/* Define the default VFD for this platform.
* Since the removal of the Windows VFD, this is sec2 for all platforms.
*/
diff --git a/src/H5queue.h b/src/H5queue.h
index 816acca..bef7ef7 100644
--- a/src/H5queue.h
+++ b/src/H5queue.h
@@ -31,8 +31,29 @@
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
+#ifndef H5queue_H_
+#define H5queue_H_
+
+/* This is a copy of netBSD's sys/queue.h header for use in HDF5. We've copied
+ * it here instead of using the system's version to avoid incompatibilities.
+ * The exception is MacOS, where other system headers make use of sys/queue.h
+ * (this may also be an issue on FreeBSD, et al.).
+ *
+ * The deprecated and unwise circular queue macros have been removed from
+ * this file to discourage their use.
+ */
+
+
+/* On MacOS, sys/file.h (needed for flock(3)) includes sys.queue.h, so we
+ * can't just use an alternative BSD queue implementation without running
+ * into symbol redefinition errors.
+ *
+ * Unfortunately, MacOS is missing SIMPLEQ, so we have to handle that
+ * separately later in the file.
+ */
+#if defined(__APPLE__)
+#include <sys/queue.h>
+#else
/*
* This file defines five types of data structures: singly-linked lists,
@@ -296,106 +317,6 @@ struct { \
} while (/*CONSTCOND*/0)
/*
- * Simple queue definitions.
- */
-#define SIMPLEQ_HEAD(name, type) \
-struct name { \
- struct type *sqh_first; /* first element */ \
- struct type **sqh_last; /* addr of last next element */ \
-}
-
-#define SIMPLEQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).sqh_first }
-
-#define SIMPLEQ_ENTRY(type) \
-struct { \
- struct type *sqe_next; /* next element */ \
-}
-
-/*
- * Simple queue access methods.
- */
-#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
-#define SIMPLEQ_END(head) NULL
-#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head))
-#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
-
-#define SIMPLEQ_FOREACH(var, head, field) \
- for ((var) = ((head)->sqh_first); \
- (var) != SIMPLEQ_END(head); \
- (var) = ((var)->field.sqe_next))
-
-#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
- for ((var) = ((head)->sqh_first); \
- (var) != SIMPLEQ_END(head) && \
- ((next = ((var)->field.sqe_next)), 1); \
- (var) = (next))
-
-/*
- * Simple queue functions.
- */
-#define SIMPLEQ_INIT(head) do { \
- (head)->sqh_first = NULL; \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (head)->sqh_first = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.sqe_next = NULL; \
- *(head)->sqh_last = (elm); \
- (head)->sqh_last = &(elm)->field.sqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (listelm)->field.sqe_next = (elm); \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
- if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
- if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
- == NULL) \
- (head)->sqh_last = &(elm)->field.sqe_next; \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
- if ((head)->sqh_first == (elm)) { \
- SIMPLEQ_REMOVE_HEAD((head), field); \
- } else { \
- struct type *curelm = (head)->sqh_first; \
- while (curelm->field.sqe_next != (elm)) \
- curelm = curelm->field.sqe_next; \
- if ((curelm->field.sqe_next = \
- curelm->field.sqe_next->field.sqe_next) == NULL) \
- (head)->sqh_last = &(curelm)->field.sqe_next; \
- } \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_CONCAT(head1, head2) do { \
- if (!SIMPLEQ_EMPTY((head2))) { \
- *(head1)->sqh_last = (head2)->sqh_first; \
- (head1)->sqh_last = (head2)->sqh_last; \
- SIMPLEQ_INIT((head2)); \
- } \
-} while (/*CONSTCOND*/0)
-
-#define SIMPLEQ_LAST(head, type, field) \
- (SIMPLEQ_EMPTY((head)) ? \
- NULL : \
- ((struct type *)(void *) \
- ((char *)((head)->sqh_last) - offsetof(struct type, field))))
-
-/*
* Tail queue definitions.
*/
#define _TAILQ_HEAD(name, type, qual) \
@@ -656,192 +577,106 @@ struct { \
((struct type *)(void *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))
-
-#ifndef _KERNEL
-/*
- * Circular queue definitions. Do not use. We still keep the macros
- * for compatibility but because of pointer aliasing issues their use
- * is discouraged!
- */
+#endif /* defined(__APPLE__) */
/*
- * __launder_type(): We use this ugly hack to work around the the compiler
- * noticing that two types may not alias each other and elide tests in code.
- * We hit this in the CIRCLEQ macros when comparing 'struct name *' and
- * 'struct type *' (see CIRCLEQ_HEAD()). Modern compilers (such as GCC
- * 4.8) declare these comparisons as always false, causing the code to
- * not run as designed.
- *
- * This hack is only to be used for comparisons and thus can be fully const.
- * Do not use for assignment.
- *
- * If we ever choose to change the ABI of the CIRCLEQ macros, we could fix
- * this by changing the head/tail sentinal values, but see the note above
- * this one.
+ * Simple queue definitions.
*/
-static __inline const void * __launder_type(const void *);
-static __inline const void *
-__launder_type(const void *__x)
-{
- __asm __volatile("" : "+r" (__x));
- return __x;
-}
-
-#if defined(QUEUEDEBUG)
-#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
- if ((head)->cqh_first != CIRCLEQ_ENDC(head) && \
- (head)->cqh_first->field.cqe_prev != CIRCLEQ_ENDC(head)) \
- QUEUEDEBUG_ABORT("CIRCLEQ head forw %p %s:%d", (head), \
- __FILE__, __LINE__); \
- if ((head)->cqh_last != CIRCLEQ_ENDC(head) && \
- (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head)) \
- QUEUEDEBUG_ABORT("CIRCLEQ head back %p %s:%d", (head), \
- __FILE__, __LINE__);
-#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
- if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) { \
- if ((head)->cqh_last != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm last %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- } else { \
- if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm forw %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- } \
- if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) { \
- if ((head)->cqh_first != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm first %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- } else { \
- if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
- QUEUEDEBUG_ABORT("CIRCLEQ elm prev %p %s:%d", \
- (elm), __FILE__, __LINE__); \
- }
-#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
- (elm)->field.cqe_next = (void *)1L; \
- (elm)->field.cqe_prev = (void *)1L;
-#else
-#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
-#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
-#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
-#endif
-
-#define CIRCLEQ_HEAD(name, type) \
+#define SIMPLEQ_HEAD(name, type) \
struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
}
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
-#define CIRCLEQ_ENTRY(type) \
+#define SIMPLEQ_ENTRY(type) \
struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
+ struct type *sqe_next; /* next element */ \
}
/*
- * Circular queue functions.
+ * Simple queue access methods.
*/
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = CIRCLEQ_END(head); \
- (head)->cqh_last = CIRCLEQ_END(head); \
-} while (/*CONSTCOND*/0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = ((var)->field.sqe_next))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->sqh_first); \
+ (var) != SIMPLEQ_END(head) && \
+ ((next = ((var)->field.sqe_next)), 1); \
+ (var) = (next))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/0)
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
} while (/*CONSTCOND*/0)
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = CIRCLEQ_END(head); \
- if ((head)->cqh_last == CIRCLEQ_ENDC(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
} while (/*CONSTCOND*/0)
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- (elm)->field.cqe_next = CIRCLEQ_END(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == CIRCLEQ_ENDC(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
} while (/*CONSTCOND*/0)
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
- QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
- if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
- QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/0)
-#define CIRCLEQ_FOREACH(var, head, field) \
- for ((var) = ((head)->cqh_first); \
- (var) != CIRCLEQ_ENDC(head); \
- (var) = ((var)->field.cqe_next))
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for ((var) = ((head)->cqh_last); \
- (var) != CIRCLEQ_ENDC(head); \
- (var) = ((var)->field.cqe_prev))
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
-/*
- * Circular queue access methods.
- */
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-/* For comparisons */
-#define CIRCLEQ_ENDC(head) (__launder_type(head))
-/* For assignments */
-#define CIRCLEQ_END(head) ((void *)(head))
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-#define CIRCLEQ_EMPTY(head) \
- (CIRCLEQ_FIRST(head) == CIRCLEQ_ENDC(head))
-
-#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
- (((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
- ? ((head)->cqh_first) \
- : (elm->field.cqe_next))
-#define CIRCLEQ_LOOP_PREV(head, elm, field) \
- (((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
- ? ((head)->cqh_last) \
- : (elm->field.cqe_prev))
-#endif /* !_KERNEL */
-
-#endif /* !_SYS_QUEUE_H_ */
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_LAST(head, type, field) \
+ (SIMPLEQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->sqh_last) - offsetof(struct type, field))))
+
+#endif /* H5queue_H_ */