File size: 13,639 Bytes
96dc096 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | /**
* 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");
|