Pkp
Pkp

Reputation: 969

Linux Kernel: Wait for other threads to complete

I have a linux kernel module, I had to implement a TCP server and multiple clients to send some traffic. I had a question,

Now at the server end, I have a main-kthread which spawns another kthread once it sees a TCP connection waiting to be Accepted. Now after the main kthread spawns say a couple of kthreads how can I put the main-kthread in wait state to make sure the other kthreads exit before the main-kthread can exit.

I am looking something similar to phtread-join semantics, but i need this in the Linux kernel space.

I could not find kthread_join as such, I am looking at alternatives. I did read about waitqueues. Hence was looking at interruptible_sleep_on() and wake_up(). But am unable to figure out how to use these API's.
For example,
In the main-thread, I do a interruptible_sleep_on, then who should wake him up? All the other threads, or the last thread? how do i figure who is the last thread exiting? Also how to make sure, the other threads have exited when this main-kthread is woken up.

Upvotes: 2

Views: 3738

Answers (1)

Wait queues are the right tools. There is a good description in Linux Device Drivers (LDD) chapter 6. Here's a sketch of how your code might look like:

  • Maintain a counter of server threads.
  • Increment the counter just before spawning a server thread.
  • When the server thread exists, decrease the counter.
  • In the main thread, when exiting, wait on a wait queue until the counter value is 0.
  • In the server threads, just after decreasing the counter, notify the main thread by signaling on the wait queue.

Warning: untested code, this is just a skeleton.

struct global_data {
    wait_queue_head_t wq;
    atomic_t thread_count;
};

main_thread () {
    global_data gd = {0};
    init_wait_queue_head(&gd.wq);
    while (serving) {
        …
        atomic_inc(&server_threads);
        if (IS_ERR_OR_NULL(kthread_create(server_thread, &gd)) {
            atomic_dec(&server_threads);
        }
    }
    wait_event_interruptible(&gd.wq, atomic_read(gd.thread_count) == 0);
    /* final cleanup */
}

server_thread (global_data *gd) {
    …
    atomic_dec(&gd->server_threads);
    wake_up(&gd->wq);
}

Upvotes: 3

Related Questions