asos-syscall-os / kernel-module /ring_buffer.c
SNAPKITTYWEST's picture
push from SNAPKITTYWEST/asos-syscall-os
96dc096 verified
Raw
History Blame Contribute Delete
13.6 kB
/**
* ring_buffer.c
* ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช ุงู„ุญู„ู‚ูŠ - ู†ู‚ู„ ุตูุฑ ู†ุณุฎุฉ
* Ring Buffer - Zero-Copy Intent Transport
*
* Lock-free SPSC (Single Producer Single Consumer) ring buffer
* for passing intent payloads between user space and kernel.
*
* Author: Ahmad Ali Parr
* License: Sovereign Source
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include <asm/atomic.h>
#include <asm/barrier.h>
#include "intent_schema.h"
#include "ring_buffer.h"
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Ring Buffer State | ุญุงู„ุฉ ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
struct IntentRing {
struct RingBufferEntry *entries; /* Ring buffer entries */
size_t capacity; /* Total slots (power of 2) */
atomic_t head; /* Producer write position */
atomic_t tail; /* Consumer read position */
atomic_t active_count; /* Number of in-flight intents */
void *mmap_base; /* mmap'd region for userspace */
size_t mmap_size; /* Size of mapped region */
};
/* Default ring capacity (must be power of 2) */
#define DEFAULT_RING_CAPACITY 256
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Ring Buffer Lifecycle | ุฏูˆุฑุฉ ุญูŠุงุฉ ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
/**
* ring_buffer_create - Allocate and initialize a new intent ring
* @capacity: Number of ring slots (must be power of 2)
*
* Returns: Pointer to IntentRing on success, NULL on failure
*/
struct IntentRing *ring_buffer_create(size_t capacity)
{
struct IntentRing *ring;
size_t alloc_size;
/* Validate capacity is power of 2 */
if (capacity == 0 || (capacity & (capacity - 1)) != 0) {
pr_err("ASOS Ring: capacity must be power of 2, got %zu\n", capacity);
return NULL;
}
/* Allocate ring structure */
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring) {
pr_err("ASOS Ring: failed to allocate ring structure\n");
return NULL;
}
/* Allocate ring buffer entries */
alloc_size = capacity * sizeof(struct RingBufferEntry);
ring->entries = vmalloc_user(alloc_size);
if (!ring->entries) {
pr_err("ASOS Ring: failed to allocate %zu bytes for entries\n", alloc_size);
kfree(ring);
return NULL;
}
/* Initialize all entries to empty state */
memset(ring->entries, 0, alloc_size);
ring->capacity = capacity;
atomic_set(&ring->head, 0);
atomic_set(&ring->tail, 0);
atomic_set(&ring->active_count, 0);
ring->mmap_base = ring->entries;
ring->mmap_size = alloc_size;
pr_info("ASOS Ring: created ring buffer with %zu slots (%zu KB)\n",
capacity, alloc_size / 1024);
return ring;
}
/**
* ring_buffer_destroy - Free ring buffer resources
* @ring: Ring to destroy
*/
void ring_buffer_destroy(struct IntentRing *ring)
{
if (!ring)
return;
if (ring->entries)
vfree(ring->entries);
kfree(ring);
pr_info("ASOS Ring: destroyed ring buffer\n");
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Producer Operations (User Space) | ุนู…ู„ูŠุงุช ุงู„ู…ู†ุชุฌ
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
/**
* ring_buffer_submit - Submit intent from user space
* @ring: Target ring
* @user_intent: User-space pointer to intent
*
* Returns: 0 on success, negative error code on failure
*
* This is called from user space via syscall. The intent is copied
* safely from user memory into the ring buffer.
*/
int ring_buffer_submit(struct IntentRing *ring,
const struct SystemIntent __user *user_intent)
{
struct RingBufferEntry *entry;
struct SystemIntent intent;
unsigned int head, next_head;
unsigned int tail;
if (!ring || !user_intent)
return -EINVAL;
/* Copy intent from user space */
if (copy_from_user(&intent, user_intent, sizeof(intent)))
return -EFAULT;
/* Validate intent structure */
if (intent.payload_len > MAX_INTENT_PAYLOAD) {
pr_warn("ASOS Ring: payload too large (%u > %u)\n",
intent.payload_len, MAX_INTENT_PAYLOAD);
return EINVALID_INTENT;
}
/* Load current head and tail (with acquire semantics) */
head = atomic_read(&ring->head);
tail = atomic_read(&ring->tail);
/* Calculate next head position (wrap using mask) */
next_head = (head + 1) & (ring->capacity - 1);
/* Check if ring is full */
if (next_head == tail) {
pr_warn("ASOS Ring: buffer full (head=%u, tail=%u)\n", head, tail);
return -EAGAIN;
}
/* Get entry at head position */
entry = &ring->entries[head];
/* Ensure entry is empty (defensive check) */
if (entry->state != RB_STATE_EMPTY) {
pr_err("ASOS Ring: entry %u not empty (state=%u)\n", head, entry->state);
return -EBUSY;
}
/* Fill entry (intent payload) */
entry->sequence = head;
memcpy(&entry->intent, &intent, sizeof(intent));
/* Memory barrier: ensure intent is visible before state change */
smp_wmb();
/* Mark entry as submitted */
entry->state = RB_STATE_SUBMITTED;
/* Memory barrier: ensure state is visible before head update */
smp_wmb();
/* Advance head pointer */
atomic_set(&ring->head, next_head);
atomic_inc(&ring->active_count);
pr_debug("ASOS Ring: submitted intent type=%u at slot %u\n",
intent.intent_type, head);
return 0;
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Consumer Operations (Kernel) | ุนู…ู„ูŠุงุช ุงู„ู…ุณุชู‡ู„ูƒ
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
/**
* ring_buffer_consume - Consume next intent from ring
* @ring: Source ring
* @intent_out: Output buffer for intent (kernel memory)
*
* Returns: 0 on success, -EAGAIN if empty, negative on error
*
* Called by KAR dispatcher to fetch the next intent for processing.
*/
int ring_buffer_consume(struct IntentRing *ring, struct SystemIntent *intent_out)
{
struct RingBufferEntry *entry;
unsigned int tail;
if (!ring || !intent_out)
return -EINVAL;
/* Load current tail */
tail = atomic_read(&ring->tail);
/* Get entry at tail position */
entry = &ring->entries[tail];
/* Memory barrier: ensure we see latest state */
smp_rmb();
/* Check if entry is ready for consumption */
if (entry->state != RB_STATE_SUBMITTED) {
/* Ring is empty or entry not yet submitted */
return -EAGAIN;
}
/* Mark entry as processing */
entry->state = RB_STATE_PROCESSING;
/* Memory barrier: ensure state change is visible */
smp_wmb();
/* Copy intent to output buffer */
memcpy(intent_out, &entry->intent, sizeof(*intent_out));
pr_debug("ASOS Ring: consumed intent type=%u from slot %u\n",
intent_out->intent_type, tail);
return 0;
}
/**
* ring_buffer_complete - Mark intent processing complete
* @ring: Target ring
* @result: Processing result to write back
*
* Returns: 0 on success, negative on error
*
* Called by KAR after intent processing completes. Writes result
* back to ring buffer and advances tail pointer.
*/
int ring_buffer_complete(struct IntentRing *ring,
const struct IntentResult *result)
{
struct RingBufferEntry *entry;
unsigned int tail, next_tail;
if (!ring || !result)
return -EINVAL;
/* Load current tail */
tail = atomic_read(&ring->tail);
/* Get entry at tail position */
entry = &ring->entries[tail];
/* Defensive check: entry should be in processing state */
if (entry->state != RB_STATE_PROCESSING) {
pr_err("ASOS Ring: entry %u not processing (state=%u)\n",
tail, entry->state);
return -EINVAL;
}
/* Write result back */
memcpy(&entry->result, result, sizeof(entry->result));
/* Memory barrier: ensure result is visible before state change */
smp_wmb();
/* Mark entry as done */
entry->state = RB_STATE_DONE;
/* Memory barrier: ensure state is visible */
smp_wmb();
/* Calculate next tail (wrap) */
next_tail = (tail + 1) & (ring->capacity - 1);
/* Advance tail pointer */
atomic_set(&ring->tail, next_tail);
atomic_dec(&ring->active_count);
/* After user space reads result, it will reset state to RB_STATE_EMPTY */
pr_debug("ASOS Ring: completed intent at slot %u, status=%d\n",
tail, result->status);
return 0;
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Ring Buffer Status | ุญุงู„ุฉ ุงู„ู…ุฎุฒู† ุงู„ู…ุคู‚ุช
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
/**
* ring_buffer_stats - Get ring buffer statistics
* @ring: Target ring
* @head_out: Output for current head position
* @tail_out: Output for current tail position
* @active_out: Output for number of active intents
*
* Returns: 0 on success
*/
int ring_buffer_stats(struct IntentRing *ring,
unsigned int *head_out,
unsigned int *tail_out,
unsigned int *active_out)
{
if (!ring)
return -EINVAL;
if (head_out)
*head_out = atomic_read(&ring->head);
if (tail_out)
*tail_out = atomic_read(&ring->tail);
if (active_out)
*active_out = atomic_read(&ring->active_count);
return 0;
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Memory Mapping (for zero-copy from user space) | ุชุนูŠูŠู† ุงู„ุฐุงูƒุฑุฉ
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
/**
* ring_buffer_mmap - Map ring buffer into user space
* @ring: Ring to map
* @vma: Virtual memory area from mmap() syscall
*
* Returns: 0 on success, negative on error
*
* Allows user space to directly access ring buffer for zero-copy
* operation (advanced usage โ€” default is copy-based submit).
*/
int ring_buffer_mmap(struct IntentRing *ring, struct vm_area_struct *vma)
{
unsigned long size;
unsigned long pfn;
int ret;
if (!ring || !vma)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
/* Validate requested size */
if (size != ring->mmap_size) {
pr_err("ASOS Ring: mmap size mismatch (req=%lu, actual=%zu)\n",
size, ring->mmap_size);
return -EINVAL;
}
/* Map pages to user space */
pfn = vmalloc_to_pfn(ring->mmap_base);
ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
if (ret) {
pr_err("ASOS Ring: mmap failed, error=%d\n", ret);
return ret;
}
pr_info("ASOS Ring: mapped %lu bytes to user space at 0x%lx\n",
size, vma->vm_start);
return 0;
}
/* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
* Module Metadata | ุจูŠุงู†ุงุช ูˆุญุฏุฉ ุงู„ู†ู…ุท
* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
MODULE_LICENSE("Proprietary");
MODULE_AUTHOR("Ahmad Ali Parr <ahmedparr93@gmail.com>");
MODULE_DESCRIPTION("ASOS Ring Buffer - Zero-Copy Intent Transport");
MODULE_VERSION("1.0.0");