Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

kthread_work and kthread_worker functionality

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:

  1. Any clarification on the unclear fields.

  2. 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?

like image 333
Natasha Avatar asked Nov 25 '15 06:11

Natasha


1 Answers

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
};
like image 197
Tsyvarev Avatar answered Dec 02 '22 19:12

Tsyvarev