1

I am developing a kernel module for the Linux kernel. Basically, what I need to do is populating /dev with some special char devices. Upon a write operation on such devices, I need to store the message and then make it available to readers after a timeout. I thought about implementing this with Linux work queues and it works, however, I am forced to allocate dynamic memory with vmalloc() for every write request:

struct delayed_message {
    struct delayed_work delayed_work;
    struct list_head list;
    struct group *group;
    struct message *message;
};

delayed_message = vmalloc(sizeof(struct delayed_message));
if (!delayed_message) {
    printk(KERN_ERR "%s: delayed write error: vmalloc failed on delayed message allocation\n",
           KBUILD_MODNAME);
    ret = -ENOMEM;
    goto free_message_buffer;
}

INIT_DELAYED_WORK(&delayed_message->delayed_work, &publisher_work);
delayed_message->group = group;
delayed_message->message = message;

queue_delayed_work(group->work_queue, &delayed_message->delayed_work, msecs_to_jiffies(group->delay_ms));

// Keep the pointer to the delayed message
spin_lock(&group->delayed_messages_spinlock);
list_add_tail(&delayed_message->list, &group->delayed_messages);
spin_unlock(&group->delayed_messages_spinlock);

Is there a safe way to reclaim the memory without interfering with the work queue?

GiuDaquan
  • 13
  • 3
  • Is this something where a ring buffer could help? – tadman Oct 02 '20 at 07:08
  • I am already keeping track of the delayed_message structs allocations using a list. – GiuDaquan Oct 02 '20 at 07:12
  • You could always have a pool of "lightly used" structures you can pull from instead of allocating if allocating is proving to be a *measurable performance problem*. This is pretty easy to do if you add a `next` pointer to the structure for this purpose, or for more memory compactness, use a `union` for such a purpose. You could also use `struct message*` with some casting in a pinch. – tadman Oct 02 '20 at 07:14
  • Sure, this would work. However, i cannot make any assumption on the number of messages the device receives. If the ring buffer is filled before the first message is delivered then the module starts dropping messages. – GiuDaquan Oct 02 '20 at 07:20
  • I'd benchmark the allocation cost by over-allocating by a factor of something ridiculous, like 1000x, just to see if it hurts (e.g. 1000 allocations, 1000 frees, then 1 more allocation for "real"). If you don't notice it, forget about it. If it's painful use a linked list approach to store spare structs you can recycle. – tadman Oct 02 '20 at 07:21

0 Answers0