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