--- /dev/null
+/*
+ * PASS
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __QUEUE_H__
+#define __QUEUE_H__
+
+#define smp_mb() dmb()
+#define smp_rmb() dmb()
+#define smp_wmb() dmb()
+
+#ifdef __aarch64__
+#define dmb() __asm__ __volatile__ ("dmb sy" : : : "memory")
+#elif __arm__
+#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
+#else
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#endif
+
+#define ATOMIC_SUB __sync_sub_and_fetch
+#define ATOMIC_ADD __sync_add_and_fetch
+#define CAS __sync_bool_compare_and_swap
+#define XCHG __sync_lock_test_and_set
+
+struct queue_node {
+ void *data;
+ struct queue_node *next;
+};
+
+struct queue {
+ struct queue_node *head;
+ struct queue_node *tail;
+};
+
+static inline void cpu_relax(void)
+{
+ asm volatile("yield" ::: "memory");
+}
+
+int enqueue(struct queue *queue, void *data);
+int dequeue(struct queue *queue, void **data);
+int create_queue(struct queue **queue);
+void destroy_queue(struct queue *queue);
+
+#endif
--- /dev/null
+/*
+ * PASS
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#include <util/queue.h>
+
+int enqueue(struct queue *queue, void *data)
+{
+ struct queue_node *node;
+ struct queue_node *new_node;
+
+ new_node = (struct queue_node *)malloc(sizeof(struct queue_node));
+ if (!new_node)
+ return -ENOMEM;
+
+ new_node->data = data;
+ new_node->next = NULL;
+
+ for (;;) {
+ node = queue->tail;
+ if (CAS(&(node->next), NULL, new_node))
+ break;
+
+ CAS(&(queue->tail), node, node->next);
+ }
+ CAS(&(queue->tail), node, new_node);
+
+ return 0;
+}
+
+int dequeue(struct queue *queue, void **data)
+{
+ struct queue_node *node;
+
+ for (;;) {
+ node = queue->head;
+ if (!node->next)
+ return -ENOENT;
+
+ if (CAS(&(queue->head), node, node->next))
+ break;
+ }
+ if (data)
+ *data = (void *) node->next->data;
+ free(node);
+
+ return 0;
+}
+
+int create_queue(struct queue **queue)
+{
+ struct queue *new_queue;
+ struct queue_node *sentinel;
+
+ new_queue = (struct queue *)malloc(sizeof(struct queue));
+ if (!new_queue)
+ return -ENOMEM;
+
+ sentinel = (struct queue_node *)malloc(sizeof(struct queue_node));
+ if (!sentinel) {
+ free(new_queue);
+ return -ENOMEM;
+ }
+
+ new_queue->head = new_queue->tail = sentinel;
+ new_queue->head->data = NULL;
+ new_queue->head->next = NULL;
+
+ *queue = new_queue;
+
+ return 0;
+}
+
+void destroy_queue(struct queue *queue)
+{
+ do { } while (!dequeue(queue, NULL));
+
+ /* freeing remaining sentinel */
+ free(queue->head);
+
+ queue->head = queue->tail = NULL;
+ free(queue);
+}