| /** | |
| * 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 | |
| */ | |
| /* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| * 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) */ | |
| /* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
| * 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"); | |