/** * 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 #include #include #include #include #include #include #include #include #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 "); MODULE_DESCRIPTION("ASOS Ring Buffer - Zero-Copy Intent Transport"); MODULE_VERSION("1.0.0");