diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2021-03-02 22:30:01 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2021-03-02 22:30:01 (GMT) |
commit | ae24b82f778579795395510aee52293f41b95aad (patch) | |
tree | a27af16a2db96eeff18401a163aa8c45f4eeb879 /src | |
parent | 69b2061d68aa85c8925c15a334fc5c3fb12e377f (diff) | |
parent | db95737047fbbf967d928bf9a693d470884f4890 (diff) | |
download | hdf5-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.c | 40 | ||||
-rw-r--r-- | src/H5FDpublic.h | 16 | ||||
-rw-r--r-- | src/H5FDvfd_swmr.h | 7 | ||||
-rw-r--r-- | src/H5FDvfd_swmr_private.h | 6 | ||||
-rw-r--r-- | src/H5Fpkg.h | 3 | ||||
-rw-r--r-- | src/H5private.h | 7 | ||||
-rw-r--r-- | src/H5queue.h | 369 |
7 files changed, 150 insertions, 298 deletions
@@ -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_ */ |