6

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.

taufique
  • 2,701
  • 1
  • 26
  • 40
  • 1
    In case if someone else look at this question, the return type of the function `thread_func` must be `int`. – omerjerk Apr 14 '14 at 17:43

3 Answers3

4
  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)
{
}
0andriy
  • 4,183
  • 1
  • 24
  • 37
Vector
  • 41
  • 1
3
  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.
cdleonard
  • 6,570
  • 2
  • 20
  • 20
2

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();
}
Ilya Matveychikov
  • 3,936
  • 2
  • 27
  • 42
  • what about third problem? its most annoying. – taufique Oct 19 '12 at 13:15
  • 1
    `task1` and `task2` are invalid pointers after threads are completed. You'll need to sinchronize thread termination and module unloading. – Ilya Matveychikov Oct 19 '12 at 13:53
  • 1
    I added `schedule();` inside the loop. but it still does the same. – taufique Oct 19 '12 at 14:04
  • To the code: At the same time you may a) add a blank line between variable definitions and the code, b) add some spaces in `while ()`, c) use proper `pr_info()` (you must know that plain `printk()` shouldn't be used). Side note: With the rating you have on SO, can you please enable syntax highlighting? – 0andriy Aug 09 '23 at 04:08