#ifndef _FI_NETDIR_QUEUE_H_
#define _FI_NETDIR_QUEUE_H_
#include <windows.h>
#include "rdma/fabric.h"
#include "fi.h"
#include "fi_osd.h"
#include "netdir.h"
#ifdef __cplusplus
extern "C" {
#endif
struct nd_queue_item {
struct nd_queue_item *next;
};
__declspec(align(16)) struct nd_queue_queue {
union {
struct {
struct nd_queue_item *head;
struct nd_queue_item *tail;
};
volatile LONG64 exchange[2];
};
};
static inline void ofi_nd_queue_push_front(struct nd_queue_queue *queue,
struct nd_queue_item *item)
{
assert(queue);
item->next = 0;
BOOLEAN success;
struct {
struct nd_queue_item *head;
struct nd_queue_item *tail;
} src;
do {
src.head = queue->head;
src.tail = queue->tail;
LONG64 head = (LONG64)(src.head ? src.head : item);
LONG64 tail = (LONG64)item;
__declspec(align(16)) LONG64 compare[2] = { (LONG64)src.head, (LONG64)src.tail };
success = InterlockedCompareExchange128(
queue->exchange, tail, head, compare);
} while (!success);
if (src.tail) {
item->next = src.head;
src.head = item;
WakeByAddressAll(&src.head);
}
}
static inline void ofi_nd_queue_push(struct nd_queue_queue *queue,
struct nd_queue_item *item)
{
assert(queue);
item->next = 0;
BOOLEAN success;
struct {
struct nd_queue_item *head;
struct nd_queue_item *tail;
} src;
do {
src.head = queue->head;
src.tail = queue->tail;
LONG64 head = (LONG64)(src.head ? src.head : item);
LONG64 tail = (LONG64)item;
__declspec(align(16)) LONG64 compare[2] = {(LONG64)src.head, (LONG64)src.tail};
success = InterlockedCompareExchange128(
queue->exchange, tail, head, compare);
} while (!success);
if (src.tail) {
src.tail->next = item;
WakeByAddressAll(&src.tail->next);
}
}
static inline int ofi_nd_queue_pop(struct nd_queue_queue *queue,
struct nd_queue_item **item)
{
assert(queue);
assert(item);
int ret = 0;
BOOLEAN success;
struct {
struct nd_queue_item *head;
struct nd_queue_item *tail;
} src;
do {
src.head = queue->head;
src.tail = queue->tail;
if (!src.head)
return 0;
if (src.head != src.tail) {
void *zero = NULL;
while (!src.head->next) {
WaitOnAddress(&src.head->next, &zero, sizeof(zero), INFINITE);
}
}
LONG64 head = (LONG64)src.head->next;
LONG64 tail = (LONG64)(src.head != src.tail ? src.tail : NULL);
__declspec(align(16)) LONG64 compare[2] = {(LONG64)src.head, (LONG64)src.tail};
success = InterlockedCompareExchange128(
queue->exchange, tail, head, compare);
} while (!success);
*item = src.head;
return (*item) != NULL;
}
static inline int ofi_nd_queue_peek(struct nd_queue_queue *queue,
struct nd_queue_item **item)
{
assert(queue);
assert(item);
*item = queue->head;
return (*item) != 0;
}
#ifdef __cplusplus
}
#endif
#endif