Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<linux/module.h>
- #include<linux/kthread.h>
- #include<linux/wait.h>
- #include<linux/slab.h>
- #include<linux/rcupdate.h>
- enum thread_index {WAKING_THREAD, WRITER_THREAD, FIRST_READER_THREAD, SECOND_READER_THREAD};
- static struct thread_structure
- {
- struct task_struct *thread[4];
- } threads;
- static wait_queue_head_t wait_queue;
- static bool condition;
- static const int first_reader_number = 1, second_thread_number = 2;
- static struct rcu_struct
- {
- int number_pointer;
- struct rcu_head rcu;
- };
- struct rcu_struct *global_pointer;
- static int reader_thread(void *data)
- {
- struct rcu_struct *local_struct = NULL;
- for(;;) {
- rcu_read_lock();
- local_struct = rcu_dereference(global_pointer);
- if(local_struct)
- pr_info("[reader_number: %d] Value of \"number\" variable: %d\n", *(int *)data,local_struct->number_pointer);
- rcu_read_unlock();
- if(kthread_should_stop())
- return 0;
- set_current_state(TASK_INTERRUPTIBLE);
- if(schedule_timeout(HZ>>2))
- pr_info("Signal received!\n");
- }
- }
- void delete(struct rcu_head *rc)
- {
- struct rcu_struct *tmp = container_of(rc, struct rcu_struct, rcu);
- kfree(tmp);
- }
- static int writer_thread(void *data)
- {
- struct rcu_struct *local_struct = NULL;
- struct rcu_struct *old_pointer = NULL;
- int number = 0;
- DEFINE_WAIT(wait);
- for(;;) {
- old_pointer = NULL;
- local_struct = kmalloc(sizeof(struct rcu_struct *),GFP_KERNEL);
- if(IS_ERR(local_struct)) {
- pr_alert("Error allocating memory: %ld\n",PTR_ERR(local_struct));
- return 0;
- }
- local_struct->number_pointer = number++;
- old_pointer = global_pointer;
- rcu_assign_pointer(global_pointer,local_struct);
- synchronize_rcu();
- if(old_pointer)
- call_rcu(&old_pointer->rcu, delete);
- add_wait_queue(&wait_queue,&wait);
- while(!condition) {
- prepare_to_wait(&wait_queue,&wait,TASK_INTERRUPTIBLE);
- if(kthread_should_stop())
- return 0;
- pr_info("[writer_thread]: awake\n");
- schedule();
- }
- condition=false;
- finish_wait(&wait_queue,&wait);
- }
- }
- static int waking_thread(void *data)
- {
- for(;;) {
- if(kthread_should_stop())
- return 0;
- set_current_state(TASK_INTERRUPTIBLE);
- if(schedule_timeout(HZ))
- pr_info("Signal received!\n");
- condition=true;
- wake_up(&wait_queue);
- }
- }
- static int __init threads_init(void)
- {
- init_waitqueue_head(&wait_queue);
- threads.thread[WRITER_THREAD] = kthread_run(writer_thread,NULL,"writer_thread");
- threads.thread[WAKING_THREAD] = kthread_run(waking_thread,NULL,"waking_thread");
- threads.thread[FIRST_READER_THREAD] = kthread_run(reader_thread,(void *)&first_reader_number,"first_reader_thread");
- threads.thread[SECOND_READER_THREAD] = kthread_run(reader_thread,(void *)&second_thread_number,"second_reader_thread");
- return 0;
- }
- static void __exit threads_exit(void)
- {
- kthread_stop(threads.thread[WAKING_THREAD]);
- kthread_stop(threads.thread[WRITER_THREAD]);
- kthread_stop(threads.thread[FIRST_READER_THREAD]);
- kthread_stop(threads.thread[SECOND_READER_THREAD]);
- }
- module_init(threads_init);
- module_exit(threads_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("An example of using the kernel linux threads and an RCU mechanism.");
- MODULE_AUTHOR("Arkadiusz Chrobot <a.chrobot@tu.kielce.pl>");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement