add kqueue API
kqueues are going to form the basis for anything related to I/O and IPC. They are a lock-free, atomic FIFO queue and support multiple emitters and consumers.main
parent
5877697e64
commit
36985f51e2
@ -0,0 +1,115 @@
|
|||||||
|
/* See the end of this file for copyright and license terms. */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <arch/atom.h>
|
||||||
|
|
||||||
|
#include <gay/mm.h>
|
||||||
|
#include <gay/types.h>
|
||||||
|
#include <gay/util.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup kqueue Lock Free FIFO (kqueue)
|
||||||
|
*
|
||||||
|
* kqueue is a simple API that allows any structure to become part of a
|
||||||
|
* lock-free FIFO queue. It only uses atomic primitives and spin-wait loops,
|
||||||
|
* which makes it safe to use even from irq context. Furthermore, it supports
|
||||||
|
* multiple concurrent emitters *and* consumers, making it suitable for stuff
|
||||||
|
* like serving as the backend for a basic batch processing system distributed
|
||||||
|
* across several CPUs.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @brief Embed this into structs that you want to put in a kqueue. */
|
||||||
|
struct kq_node {
|
||||||
|
patom_t next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Lock free FIFO with support for multiple emitters and consumers. */
|
||||||
|
struct kqueue {
|
||||||
|
patom_t head;
|
||||||
|
patom_t tail;
|
||||||
|
struct kq_node _dummy;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a kqueue.
|
||||||
|
*
|
||||||
|
* @param kq kqueue to initialize
|
||||||
|
*/
|
||||||
|
static inline void kq_init(struct kqueue *kq)
|
||||||
|
{
|
||||||
|
patom_init(&kq->head, &kq->_dummy);
|
||||||
|
patom_init(&kq->tail, &kq->_dummy);
|
||||||
|
patom_init(&kq->_dummy.next, nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a new kqueue and initialize it.
|
||||||
|
*
|
||||||
|
* @param flags Flags for `kmalloc()`
|
||||||
|
* @return The initialized kqueue, or `nil` if OOM
|
||||||
|
*/
|
||||||
|
struct kqueue *kq_create(enum mflags flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add a new entry to the end of a kqueue.
|
||||||
|
*
|
||||||
|
* @param kq kqueue to append the entry to
|
||||||
|
* @param node New node to append to the queue
|
||||||
|
*/
|
||||||
|
void kq_add(struct kqueue *kq, struct kq_node *node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove the first item in a kqueue.
|
||||||
|
*
|
||||||
|
* @param kq kqueue to remove an item from
|
||||||
|
* @return The removed item, or `nil` if the queue was empty
|
||||||
|
*/
|
||||||
|
struct kq_node *kq_del(struct kqueue *kq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cast a kqueue entry out to the structure it is embedded in.
|
||||||
|
*
|
||||||
|
* @param head The `kq_node_t *` to cast out of
|
||||||
|
* @param type Type of the containing structure
|
||||||
|
* @param member Name of the `kq_node_t` within the structure
|
||||||
|
* @returns The `struct *` that `head` is embedded in
|
||||||
|
*/
|
||||||
|
#define kq_entry(head, type, member) container_of(head, type, member)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove the first item in a kqueue and return the structure
|
||||||
|
* it is embedded in.
|
||||||
|
*
|
||||||
|
* @param kq kqueue to remove an item from
|
||||||
|
* @param type Type of the containing structure
|
||||||
|
* @param member Name of the `kq_node_t` within the structure
|
||||||
|
* @returns The `struct *` that was removed from the queue,
|
||||||
|
* or `nil` if the queue was empty
|
||||||
|
*/
|
||||||
|
#define kq_del_entry(kq, type, member) ({ \
|
||||||
|
struct kq_node *__node = kq_del(kq); \
|
||||||
|
/* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
|
||||||
|
type *__entry = nil; \
|
||||||
|
if (__node != nil) \
|
||||||
|
__entry = kq_entry(__node, type, member); \
|
||||||
|
__entry; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of GayBSD.
|
||||||
|
* Copyright (c) 2021 fef <owo@fef.moe>.
|
||||||
|
*
|
||||||
|
* GayBSD is nonviolent software: you may only use, redistribute, and/or
|
||||||
|
* modify it under the terms of the Cooperative Nonviolent Public License
|
||||||
|
* (CNPL) as found in the LICENSE file in the source code root directory
|
||||||
|
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
|
||||||
|
* of the license, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||||
|
* permitted by applicable law. See the CNPL for details.
|
||||||
|
*/
|
Loading…
Reference in New Issue