I need to use the kthread functions for a work processor and the distinction between the two is not very clear to me. This is my understanding of the fields.
struct kthread_worker {
spinlock_t lock; // lock to update the work queue
struct list_head work_list; // list kthread_work items
struct task_struct *task; // handle for thread
struct kthread_work *current_work; // ?
};
struct kthread_work {
struct list_head node; // list of threads?
kthread_work_func_t func; // func to execute?
struct kthread_worker *worker; // worker associated with this work item
};
My questions are:
Any clarification on the unclear fields.
kthread_work_func_t is a func ptr expecting an argument of kthread_work. How does that work? It should point to the function you want the thread to execute, right?
kthread_worker
is a worker, which can execute works (kthread_work
). Work can be added to worker at any time. Worker executes works one by one. If no work is currently available, worker waits.
kthread_work_func_t is a func ptr expecting an argument of kthread_work. How does that work? It should point to the function you want the thread to execute, right?
Yes, it is just function you want to execute as work.
If only one work uses this function(e.g., this is some sort of garbage collector), function may simply ignore its argument.
If you want to have several works, which uses same functionality but with different parameters, you may embed kthread_work
structure into your structure, which contain these parameters:
struct my_work
{
struct kthread_work work; //Base work object
int i; // Your parameter
}
// Parametrized work function
void my_func(struct kthread_work* work)
{
// Extract actual work object
struct my_work* my_work = container_of(work, struct my_work, work);
// Parameter for the work
int i = my_work->i;
// Do something
...
// Free memory used for work object
kfree(my_work);
}
// Helper for add your work with given parameter
void add_my_work(struct kthread_worker* worker, int i)
{
// Allocate your work object on the heap
struct my_work* my_work = kmalloc(sizeof(struct my_work), GFP_KERNEL);
// Initialize base work structure
init_kthread_work(&my_work->work, &my_func);
// Store parameter
work->i = i;
queue_kthread_work(worker, &my_work->work);
}
Any clarification on the unclear fields.
As you can see from previous example, knowing fields of struct kthread_worker
and struct kthread_work
is rarely useful for just using it. But actually semantic is simple:
struct kthread_worker {
spinlock_t lock; // lock to update the work queue
struct list_head work_list; // list kthread_work items
struct task_struct *task; // handle for thread
struct kthread_work *current_work; // (+) currently executed work object
};
struct kthread_work {
struct list_head node; // (+) element in the kthread_worker.work_list
kthread_work_func_t func; // func to execute
struct kthread_worker *worker; // worker associated with this work item
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With