taufique
taufique

Reputation: 2751

Simple kernel multithreading

I am new to kernel module programming and for my work I need to write a multithreaded kernel module. So I tried some primary uses of kernel threads. I wrote the following. It is supposed to print 1 in one thread and 2 in another thread, both 10 times.

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/udp.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/kthread.h>

struct task_struct *task1;
struct task_struct *task2;


static void thread_func(void* data)
{   
    int *n;
    n = (int *)data;
    int i = 0;
    while(i < 10){
        printk("%d\n", *n);
        i++;
    }
    //do_exit();
}

static int t_start(void)
{
    printk("Module starting ... ... ..\n");
    int *p1, *p2;
    int one = 1, two = 2;
    p1 = &one;
    p2 = &two;
    task1 = kthread_run(&thread_func, (void*)p1, "thread_func_1");
    task2 = kthread_run(&thread_func, (void*)p2, "thread_func_2");
    return 0;
}

static void t_end (void)
{
    printk("Module terminating ... ... ...\n");
    kthread_stop(task1);
    kthread_stop(task2);
}

module_init(t_start);
module_exit(t_end);

MODULE_AUTHOR("Md. Taufique Hussain");
MODULE_DESCRIPTION("Testing kernel threads");
MODULE_LICENSE("GPL");

But I am facing following problems. -

  1. First thread is printing all ten 1s and then second thread is executing. I wanted to run these two in interleaved manner.
  2. First thread is printing all 1s OK but second is not printing 2s. It is printing 0s. Probably parameter is not passing to second thread properly.
  3. When I am inserting module it is running but when I am removing module the machine hangs

What are the problems? How can I solve them.

Upvotes: 6

Views: 9270

Answers (3)

Vector
Vector

Reputation: 41

  1. Don't use these in the code, delete them
// kthread_stop(task1);
// kthread_stop(task2);

it seems after the termination of the thread, task will be set to NULL, then calling kthread_stop() will cause a NULL pointer error.

  1. Don't pass local variable to threads, use global variable instead.

  2. If you want two threads switch between each other, use wait_event() and wake_up() functions. Here is my code that works.

#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/sched.h>
#include <linux/wait.h>

MODULE_LICENSE("GPL");

int pid1 = 1;
int pid2 = 2;

DECLARE_WAIT_QUEUE_HEAD(wq);

int condition;

struct task_struct *task1;
struct task_struct *task2;

static int thread_function(void *data)
{
    int *thread_id = data;
    int i = 0;

    while (i < 10) {
        pr_info("install kernel thread: %d\n", *thread_id);
        i++;

        if (*thread_id == 1) {
            wait_event(wq, condition == 0xA);

            condition = 0xB;
            wake_up(&wq);
        } else {
            wait_event(wq, condition == 0xB);

            condition = 0xA;
            wake_up(&wq);
        }
    }
    return 0;
}

static int kernel_init(void)
{
    condition = 0xA;

    task1 = kthread_create(&thread_function, &pid1, "pradeep");
    task2 = kthread_create(&thread_function, &pid2, "pradeep");

    // pr_info(KERN_INFO "After create kernel thread\n");
    wake_up_process(task1);
    wake_up_process(task2);
    return 0;
}

int init_module(void)
{
    kernel_init();
    return 0;
}

void cleanup_module(void)
{
}

Upvotes: 4

cdleonard
cdleonard

Reputation: 7050

  1. You need schedule() unless you have a preemptible kernel and some sleeps.
  2. You are passing data pointers from the stack and thus corrupting kernel memory. Make those ints global variables.

Upvotes: 3

Ilya Matveychikov
Ilya Matveychikov

Reputation: 4024

Add schedule call to force thread scheduling.

static void thread_func(void* data)
{   
    int *n;
    n = (int *)data;
    int i = 0;
    while(i < 10){
        printk("%d\n", *n);

        schedule();

        i++;
    }
    //do_exit();
}

Upvotes: 2

Related Questions