1

I'm learning how the kernel handles interrupt.
Reading shichao's notes, I've found that events/n threads handle the work queue.
At the same time, some documents in the internet (for example, this post), say like this

"kworker" is a placeholder process for kernel worker threads, which perform most of the actual processing for the kernel, especially in cases where there are interrupts, timers, I/O, etc.

They seem similar for me and I'm a little confusing: are events/n threads and kworker threads same? If so, has events/n been renamed to kworker? If not, what is the difference between events/n and kworker?

I can find kworker (ex, kworker/1:0) through htop, but I can't see events/n.

0

I think I may have an answer for this. The summary seems to be that there was a name change, although I have not been able to find yet documentation to that.

Details:

Shichao's notes are notes based on the book Linux Kernel Development by Robert Love. That book is based on kernel version 2.16.34. The snippets of code in the notes match the code in file kernel/workqueue.c for that version:

/*
 * The per-CPU workqueue (if single thread, we always use the first
 * possible cpu).
 */
struct cpu_workqueue_struct {

        spinlock_t lock;

        struct list_head worklist;
        wait_queue_head_t more_work;
        struct work_struct *current_work;

        struct workqueue_struct *wq;
        struct task_struct *thread;
} ____cacheline_aligned;

/*
 * The externally visible workqueue abstraction is an array of
 * per-CPU workqueues:
 */
struct workqueue_struct {
        struct cpu_workqueue_struct *cpu_wq;
        struct list_head list;
        const char *name;
        int singlethread;
        int freezeable;         /* Freeze threads during suspend */
        int rt;
#ifdef CONFIG_LOCKDEP
        struct lockdep_map lockdep_map;
#endif
};

That Linux version seems was using the init_workqueues function to create the work queues:

void __init init_workqueues(void)
{
        ...
        keventd_wq = create_workqueue("events");
}

Robert Love's book on page 154 section "Create Queues" says"

You create a new work queue and the associated worker threads via a simple function: struct workqueue_struct *create_workqueue(const char *name); The parameter name is used to name the kernel threads

So, it seems quite indicative that the above code then is why the worker threads were named "events" then.

Newer code, looking at 4.19, has several differences. First, the workqueue_struct is much more extensive and the cpu_workqueue_struct no longer exists. Now there are pools and the creation of the workqueue worker thread is done by a function named create_worker in a pool. Inside that function, the "kworker/%s" kthread is created as can be seen in the code snippet below:

/**
 * create_worker - create a new workqueue worker
 * @pool: pool the new worker will belong to
 *
 * Create and start a new worker which is attached to @pool.
 *
 * CONTEXT:
 * Might sleep.  Does GFP_KERNEL allocations.
 *
 * Return:
 * Pointer to the newly created worker.
 */
static struct worker *create_worker(struct worker_pool *pool)
{
        ...
        worker->task = kthread_create_on_node(worker_thread, worker, pool->node,
                                              "kworker/%s", id_buf);
        ...
}

So, this is as far as I could get on this. If anybody has more precisions or corrections, I would love to hear them.

As for the definitive information on work queues, it is in this kernel doc

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.