examples/kerneltest/kernel_module.c
author Edouard Tisserant
Mon, 23 Apr 2018 12:32:03 +0200
changeset 805 570e3a444023
parent 467 40efa79d27dd
permissions -rw-r--r--
Workaround Alchemy task not beeing waken up when closing file descriptor it is waiting on, sequel of Xenomai3 all posix file ops
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     1
#include <linux/module.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     2
#include <linux/kthread.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     3
#include <linux/fs.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     4
#include <linux/cdev.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     5
#include <asm/uaccess.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     6
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     7
#include "TestMasterSlave.h"
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     8
#include "console/console.h"
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     9
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    10
#define minor 0
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    11
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    12
MODULE_LICENSE("GPL");
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    13
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    14
static dev_t canftest_dev;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    15
static struct cdev *canftest_cdev;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    16
static struct task_struct *thread_start_p, *thread_stop_p;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    17
static DECLARE_MUTEX (canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    18
static int canftest_stopped = 1;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    19
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    20
int thread_start (void* data);
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    21
int thread_stop (void* data);
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    22
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    23
// handler processing write() requests from user-space
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    24
ssize_t canftest_write(struct file *filp, const char __user *buf, size_t count,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    25
		       loff_t *f_pos)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    26
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    27
	int cmd;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    28
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    29
	// get integer from user-space
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    30
	if (get_user (cmd, buf))
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    31
		return -EFAULT;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    32
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    33
	// process integer as command
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    34
	switch (cmd) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    35
		case CMD_START:
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    36
			if (!canftest_stopped) break;
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    37
			thread_start_p = kthread_create (thread_start, NULL, "canftest_start");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    38
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    39
			if (PTR_ERR(thread_start_p) == -ENOMEM) {
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    40
				printk(KERN_WARNING "canftest: error creating start thread\n");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    41
				return -ENOMEM;
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    42
			}
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    43
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    44
			wake_up_process (thread_start_p);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    45
			break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    46
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    47
		case CMD_STOP:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    48
			if (canftest_stopped) break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    49
			thread_stop_p = kthread_create (thread_stop, NULL, "canftest_stop");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    50
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    51
			if (PTR_ERR(thread_stop_p) == -ENOMEM) {
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    52
				printk(KERN_WARNING "canftest: error creating stop thread\n");
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    53
				return -ENOMEM;
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    54
			}
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    55
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    56
			wake_up_process (thread_stop_p);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    57
			break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    58
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    59
		// ignore new line character
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    60
		case 10:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    61
			break;
467
40efa79d27dd kerneltest updated for the new api
greg
parents: 391
diff changeset
    62
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    63
		default:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    64
			printk("canftest: bad command %d\n", cmd);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    65
			break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    66
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    67
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    68
	return count;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    69
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    70
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    71
// register write() handler
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    72
static struct file_operations canftest_fops = {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    73
	.owner =    THIS_MODULE,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    74
	.write =    canftest_write,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    75
};
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    76
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    77
// start TestMasterSlave example
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    78
int thread_start (void* data)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    79
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    80
	int ret=0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    81
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    82
	down_interruptible (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    83
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    84
	ret=TestMasterSlave_start();
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    85
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    86
	// if started
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    87
	if (ret == 0) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    88
		canftest_stopped = 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    89
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    90
		// increment module usage count
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    91
		try_module_get(THIS_MODULE);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    92
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    93
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    94
	up (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    95
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    96
	return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    97
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    98
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    99
// finish TestMasterSlave example
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   100
int thread_stop (void* data)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   101
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   102
	down_interruptible (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   103
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   104
	TestMasterSlave_stop();
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   105
	canftest_stopped = 1;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   106
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   107
	// decrement usage count
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   108
	module_put(THIS_MODULE);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   109
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   110
	up (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   111
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   112
	return 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   113
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   114
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   115
int init_module(void)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   116
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   117
	int ret, major;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   118
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   119
	// get major device number dynamically
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   120
	ret = alloc_chrdev_region(&canftest_dev, minor, 1, DEVICE_NAME);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   121
	major = MAJOR(canftest_dev);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   122
	if (ret < 0) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   123
		printk(KERN_WARNING "canftest: can't get major %d\n", major);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   124
		return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   125
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   126
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   127
	canftest_cdev = cdev_alloc( );
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   128
	canftest_cdev->owner = THIS_MODULE;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   129
	canftest_cdev->ops = &canftest_fops;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   130
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   131
	// register new character device
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   132
	ret = cdev_add (canftest_cdev, canftest_dev, 1);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   133
	if (ret) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   134
		printk(KERN_WARNING "canftest: error %d adding char device\n", ret);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   135
		return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   136
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   137
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   138
	return 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   139
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   140
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   141
void cleanup_module(void)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   142
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   143
	// unregister major device number and character device
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   144
	unregister_chrdev_region(canftest_dev, 1);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   145
	cdev_del(canftest_cdev);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   146
}