diff --git a/kernel/kmod.c b/kernel/kmod.c index 806a5ea69fa1764ae8dbceefb640b7af0bfe9d0c..0c46b82ac53e1a82623f0c2f8d959a13ffef67b4 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/kthread.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/uaccess.h> #include <linux/vmalloc.h> @@ -15,7 +16,7 @@ #define CLASS_NAME "sibyl_class" #define SLOTS 4 -#define SLOT_INTERVAL_NS 10000000 +#define SLOT_INTERVAL_NS 1000000000 #define MAX_MEASUREMENTS 16 @@ -43,10 +44,16 @@ static struct task_struct *timed_thread; static DECLARE_WAIT_QUEUE_HEAD(wq); static atomic_t wake_counter = ATOMIC_INIT(0); +// Send Buffers #define SEND_BUFFER_SIZE 4096 -static uint8_t send_buffer[SEND_BUFFER_SIZE]; -static size_t send_buffer_size = 0; +static struct mutex send_buffer_mutex; + +static uint8_t *primary_send_buffer; +static size_t primary_send_buffer_size = 0; + +static uint8_t *secondary_send_buffer; +static size_t secondary_send_buffer_size = 0; static int slot = 0; @@ -55,7 +62,8 @@ static int device_open(struct inode *inode, struct file *file) { return 0; } static int device_release(struct inode *inode, struct file *file) { return 0; } static uint32_t calculate_crc32(const packet_t *packet) { - uint32_t crc = crc32(0, (void *)&packet->data.sender_id, sizeof(uint8_t)); + uint32_t crc = crc32(0, (void *)&packet->magic, sizeof(uint8_t)); + crc = crc32(crc, (void *)&packet->data.sender_id, sizeof(uint8_t)); crc = crc32(crc, (void *)&packet->data.count, sizeof(uint8_t)); crc = crc32(crc, (void *)&packet->data.measurements, sizeof(measurement_t) * packet->data.count); @@ -65,24 +73,38 @@ static uint32_t calculate_crc32(const packet_t *packet) { static void prepare_for_sending(void) { packet->crc = calculate_crc32(packet); - send_buffer[0] = packet->magic; - send_buffer[1] = packet->data.sender_id; - send_buffer[2] = packet->data.count; + secondary_send_buffer[0] = packet->magic; + secondary_send_buffer[1] = packet->data.sender_id; + secondary_send_buffer[2] = packet->data.count; uint8_t *bytes = (uint8_t *)packet->data.measurements; for (size_t i = 0; i < sizeof(measurement_t) * packet->data.count; i++) { - send_buffer[3 + i] = bytes[i]; + secondary_send_buffer[3 + i] = bytes[i]; } bytes = (uint8_t *)&packet->crc; for (size_t i = 0; i < sizeof(uint32_t); i++) { - send_buffer[3 + sizeof(measurement_t) * packet->data.count + i] = bytes[i]; + secondary_send_buffer[3 + sizeof(measurement_t) * packet->data.count + i] = + bytes[i]; } - send_buffer_size = + secondary_send_buffer_size = 3 + sizeof(measurement_t) * packet->data.count + sizeof(uint32_t); + + // Swap buffers + mutex_lock(&send_buffer_mutex); + + uint8_t *tmp = primary_send_buffer; + primary_send_buffer = secondary_send_buffer; + secondary_send_buffer = tmp; + + size_t tmp_size = primary_send_buffer_size; + primary_send_buffer_size = secondary_send_buffer_size; + secondary_send_buffer_size = tmp_size; + + mutex_unlock(&send_buffer_mutex); } static ssize_t device_write(struct file *filp, const char *input, size_t length, @@ -144,10 +166,17 @@ static inline void send_byte(uint8_t byte) { send_bit(1); } -static void send_data(const packet_t *packet) { - for (size_t i = 0; i < send_buffer_size; i++) { - send_byte(send_buffer[i]); +static void send_buffer(void) { + printk(KERN_INFO "Send %zu bytes\n", primary_send_buffer_size); + + unsigned long flags; + local_irq_save(flags); + + for (size_t i = 0; i < primary_send_buffer_size; i++) { + send_byte(primary_send_buffer[i]); } + + local_irq_restore(flags); } static int timed_thread_fn(void *args) { @@ -156,7 +185,9 @@ static int timed_thread_fn(void *args) { atomic_dec(&wake_counter); if (slot == 0) { - send_data(packet); + mutex_lock(&send_buffer_mutex); + send_buffer(); + mutex_unlock(&send_buffer_mutex); } slot = (slot + 1) % SLOTS; @@ -168,6 +199,9 @@ static int timed_thread_fn(void *args) { static int __init lkm_init(void) { dev_t dev; + mutex_init(&send_buffer_mutex); + + // Allocate memory for packet packet = (packet_t *)vmalloc(sizeof(packet_t)); if (packet == NULL) { @@ -188,8 +222,27 @@ static int __init lkm_init(void) { prepare_for_sending(); - // Dynamically allocate major number + // Allocate memory for send buffers + primary_send_buffer = (uint8_t *)vmalloc(SEND_BUFFER_SIZE); + primary_send_buffer_size = 0; + if (primary_send_buffer == NULL) { + vfree(packet->data.measurements); + vfree(packet); + return -EFAULT; + } + + secondary_send_buffer = (uint8_t *)vmalloc(SEND_BUFFER_SIZE); + secondary_send_buffer_size = 0; + if (secondary_send_buffer == NULL) { + vfree(primary_send_buffer); + vfree(packet->data.measurements); + vfree(packet); + return -EFAULT; + } + if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) { + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); printk(KERN_ALERT "Failed to allocate major number\n"); @@ -199,6 +252,8 @@ static int __init lkm_init(void) { class = class_create(CLASS_NAME); if (IS_ERR(class)) { + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); unregister_chrdev_region(MKDEV(major_number, 0), 1); @@ -208,6 +263,8 @@ static int __init lkm_init(void) { if (device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME) == NULL) { + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); class_destroy(class); @@ -218,6 +275,8 @@ static int __init lkm_init(void) { cdev_init(&mycdev, &fops); if (cdev_add(&mycdev, MKDEV(major_number, 0), 1) < 0) { + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); device_destroy(class, MKDEV(major_number, 0)); @@ -230,6 +289,8 @@ static int __init lkm_init(void) { printk(KERN_INFO "lkm: device created successfully\n"); if (gpio_request(GPIO_PIN, "GPIO_PIN") < 0) { + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); cdev_del(&mycdev); @@ -243,6 +304,8 @@ static int __init lkm_init(void) { timed_thread = kthread_run(timed_thread_fn, NULL, "timed_thread"); if (IS_ERR(timed_thread)) { + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); cdev_del(&mycdev); @@ -262,6 +325,10 @@ static int __init lkm_init(void) { } static void __exit lkm_exit(void) { + mutex_destroy(&send_buffer_mutex); + + vfree(primary_send_buffer); + vfree(secondary_send_buffer); vfree(packet->data.measurements); vfree(packet); cdev_del(&mycdev);